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 }

 

posted @ 2017-08-25 20:54  Kaiser-  阅读(277)  评论(0编辑  收藏  举报