bzoj2118

题目大意:给定n个物品,每个物品有一个非负价值,问[L,R]区间内有多少价值可以被凑出来。

题意网上一大片,具体求解过程是利用了加法原理,将各个模数拥有的个数之和相加。

就是说随机取一个数a[k],那么就是对于每个模数,通过转移的方式求出到达每个模数的最短路,将每个模数

0-(a[k]-1)之间的数连每个对应的a[j] (%a[k])意义下,花费为路的长度,这样就好了,最后前缀和相减求答案。

 1 #include<cmath>
 2 #include<queue>
 3 #include<cstdio>
 4 #include<vector>
 5 #include<cstring>
 6 #include<iostream>
 7 #include<algorithm>
 8 using namespace std;
 9
10 typedef long long ll;
11 typedef pair<ll,int>fzy;
12 const ll INF=1e16+7;
13
14
15 int n;
16 int a[17];
17 int cnt,head[500007],next[5000007],rea[5000007],val[5000007];
18 ll ans=0,l,r,dis[500007];
19 bool boo[500007];
20
21 struct cmp
22 {
23     bool operator()(fzy x,fzy y)
24     {
25         return x.first>y.first;
26     }
27 };
28 priority_queue<fzy,vector<fzy>,cmp>q;
29
30 void add(int u,int v,int fee)
31 {
32     cnt++;
33     next[cnt]=head[u];
34     head[u]=cnt;
35     rea[cnt]=v;
36     val[cnt]=fee;
37 }
38 void Dijkstra()
39 {
40     for (int i=0;i<a[1];i++)
41         dis[i]=INF,boo[i]=0;
42     dis[0]=0;
43     q.push(make_pair(0,0));
44     while (!q.empty())
45     {
46         fzy now=q.top();
47         q.pop();
48         int u=now.second;
49         if (boo[u]) continue;boo[u]=1;
50         for (int i=head[u];i!=-1;i=next[i])
51         {
52             int v=rea[i],fee=val[i];
53             if (dis[v]>dis[u]+fee)
54             {
55                 dis[v]=dis[u]+fee;
56                 q.push(make_pair(dis[v],v));
57             }
58         }
59     }
60 }
61 int main()
62 {
63     memset(head,-1,sizeof(head));
64     scanf("%d%lld%lld",&n,&l,&r);
65     for (int i=1;i<=n;i++)
66         scanf("%d",&a[i]);
67     sort(a+1,a+n+1);
68     for (int i=0;i<a[1];i++)
69         for (int j=2;j<=n;j++)
70             add(i,(a[j]+i)%a[1],a[j]);
71     Dijkstra();
72     for (int i=0;i<a[1];i++)
73     if (dis[i]<=r)
74     {
75         ll x=max((ll)0,(l-dis[i])/a[1]),y=(ll)(r-dis[i])/a[1];
76         if (x*a[1]+dis[i]<l) x++;
77         if (y*a[1]+dis[i]>r) y--;
78         ans+=y-x+1;
79     }
80     printf("%lld\n",ans);
81 }
时间: 2025-01-03 17:18:01

bzoj2118的相关文章

【bzoj2118】 墨墨的等式

http://www.lydsy.com/JudgeOnline/problem.php?id=2118 (题目链接) 题意 给出B的取值范围[Bmin,Bmax],求方程a1x1+a2x2+…+anxn=B有多少B可以使等式存在非负整数解. Solution 问题很容易就被转化为:用a1,a2,a3,······an能组成多少个在范围[Bmin,Bmax]内的数.这是一类经典的图论问题. 我们假设a[]中最小的元素为T,可以考虑用n个数能够组成的数对T的模的情况.用dis[i]表示构成的一个数

bzoj2118 墨墨的等式

2118: 墨墨的等式 Time Limit: 10 Sec  Memory Limit: 259 MB Description 墨墨突然对等式很感兴趣,他正在研究a1x1+a2y2+-+anxn=B存在非负整数解的条件,他要求你编写一个程序,给定N.{an}.以及B的取值范围,求出有多少B可以使等式存在非负整数解. Input 输入的第一行包含3个正整数,分别表示N.BMin.BMax分别表示数列的长度.B的下界.B的上界.输入的第二行包含N个整数,即数列{an}的值. Output 输出一个

BZOJ2118墨墨的等式[数论 最短路建模]

2118: 墨墨的等式 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 1317  Solved: 504[Submit][Status][Discuss] Description 墨墨突然对等式很感兴趣,他正在研究a1x1+a2y2+…+anxn=B存在非负整数解的条件,他要求你编写一个程序,给定N.{an}.以及B的取值范围,求出有多少B可以使等式存在非负整数解. Input 输入的第一行包含3个正整数,分别表示N.BMin.BMax分别表示数

[bzoj2118]墨墨的等式【dijk+堆】

编译器真是神经了  k=k*2打成了k*2居然都不报错  还一点事情没有 害我改一晚上 一开始忘记了c++的数组默认从0开始 后来又把dijk写T了.....重申一遍,这里是先把所有点加进去然后依次pop() 至于这道题,大家都说它是一道数论好题 而狗王一定要把它当作spfa专题来讲给小朋友们听 ---erh... 网上题解有很多 首推po姐的 #include<cstdio> #define ll long long #define inf 1<<29 #include<a

-----------------------【有趣の题目】-----------------------

做过的,有意义多次看的,有趣的题目整合包 图论相关: [BZOJ-3308]九月的咖啡店   线性筛素数+有趣的处理+最大费用最大流 [BZOJ-4205]卡牌配对   线性筛素数+最大流+玄学的效率 [BZOJ-2095]Bridge   混合图欧拉回路 [BZOJ-1797]Mincut 最小割    最大流+Tarjan+缩点+分类讨论 [BZOJ-2879]美食节    最小费用最大流+拆点+动态建图 [BZOJ-1061]志愿者招募   线性规划转最小费用最大流 [BZOJ-2118]