[国家集训队]墨墨的等式(最短路优化完全背包)


题目描述

墨墨突然对等式很感兴趣,他正在研究a_1x_1+a_2x_2+…+a_nx_n=Ba1x1+a2x2++anxn=B存在非负整数解的条件,他要求你编写一个程序,给定N、{an}、以及B的取值范围,求出有多少B可以使等式存在非负整数解。

输入格式

输入的第一行包含3个正整数,分别表示NBMinBMax分别表示数列的长度、B的下界、B的上界。

输入的第二行包含N个整数,即数列{an}的值。

输出格式

输出一个整数,表示有多少b可以使等式存在非负整数解。

输入输出样例

输入 #1
2 5 10
3 5
输出 #1
5

说明/提示

对于20%的数据,N5,1BMinBMax10。

对于40%的数据,N10,1BMinBMax106。

对于100%的数据,N12,0ai5105,1BMinBMax1012。

       十分神奇的思路。

       为了优化要选择minnum作为模数。

     复杂度十分神奇 并不会证qaqq

     

 1 #include<bits/stdc++.h>
 2 #define re register int
 3 #define LL long long
 4 #define maxn 12+5
 5 #define maxn1 500000+5
 6 #define maxn2 6000000+5
 7 using namespace std;
 8 
 9 
10 
11 int n;
12 int num[maxn];
13 bool vis[maxn1];
14 LL bmin,bmax;
15 LL dis[maxn1];
16 struct edge
17 {
18     int nex,to,w;
19 }ed[maxn2];
20 int head[maxn1];
21 int cnt,mintmp; 
22 void add(int x,int y,int w)
23 {
24     ed[++cnt].to=y;
25     ed[cnt].nex=head[x];
26     ed[cnt].w=w;
27     head[x]=cnt;
28 } 
29  queue<int>q;
30  void spfa()
31  {
32      for(re i=0;i<mintmp;i++)
33      dis[i]=1926081700000;
34      q.push(0);
35      vis[0]=true;
36      dis[0]=0;
37      //cout<<dis[1]<<endl;
38      while(!q.empty())
39      {
40         int u=q.front();
41         q.pop();
42         vis[u]=false;
43         for(re i=head[u];i;i=ed[i].nex)
44             if(dis[ed[i].to]>dis[u]+ed[i].w)
45         {
46         dis[ed[i].to]=dis[u]+ed[i].w;
47             if(!vis[ed[i].to]) {
48                 q.push(ed[i].to);
49                 vis[ed[i].to]=true;
50             }
51         }
52      }
53     }
54 LL query(LL x)//LL x
55 {
56     LL ans=0;
57     for(re i=0;i<mintmp;i++)
58     if(dis[i]<=x)  ans+=(x-dis[i])/mintmp+1;
59     //是<=而不是!=1926081700000  
60     return  ans;
61 }
62 int main()
63 {
64     ios::sync_with_stdio(false);
65     cin>>n>>bmin>>bmax;
66     mintmp=maxn1;
67     for(re i=1;i<=n;i++)
68     {
69         cin>>num[i];
70         if(num[i])
71         mintmp=min(mintmp,num[i]);
72     } 
73     for(re j=0;j<mintmp;j++)
74     for(re i=1;i<=n;i++)
75     if(num[i]!=mintmp) 
76     add(j,(num[i]+j)%mintmp,num[i]);
77     //由j向(num[i]+j)%mintmp连边 
78     spfa();
79     LL sum=query(bmax)-query(bmin-1);
80 //    cout<<query(bmax)<<endl;
81 //    cout<<query(bmin-1)<<endl; 
82     cout<<sum;
83     return 0;
84 }
View Code

 

posted @ 2019-10-03 20:17  3200Phaethon  阅读(199)  评论(0编辑  收藏  举报