Description
墨墨突然对等式很感兴趣,他正在研究a1x1+a2y2+…+anxn=B存在非负整数解的条件,他要求你编写一个程序,给定N、{an}、以及B的取值范围,求出有多少B可以使等式存在非负整数解。
Input
输入的第一行包含3个正整数,分别表示N、BMin、BMax分别表示数列的长度、B的下界、B的上界。输入的第二行包含N个整数,即数列{an}的值。
Output
输出一个整数,表示有多少b可以使等式存在非负整数解。
Sample Input
2 5 10 3 5
Sample Output
5
HINT
对于100%的数据,N≤12,0≤ai≤5*10^5,1≤BMin≤BMax≤10^12。
Source
同余类最短路
在所有读入的a[i]中,找到最小的一个a为基准,在模a的意义下计算问题
假设通过一些数可以凑出x,使得x%a==j,那么通过累加a就可以凑出所有%a==j的大数。
设dis[i]表示能凑到的模a余i的最小数,SPFA算出dis数组,再利用dis计算Bmin~Bmax内可以凑出的数的个数。
一:刚开始写了建边的版本,但是因为要连的边太多了,常数爆炸,4000+ms通过
1 #include2 #include 3 #include 4 #include 5 #include 6 #define LL long long 7 using namespace std; 8 const int mxn=500100; 9 int read(){10 int x=0,f=1;char ch=getchar();11 while(ch<'0' || ch>'9'){ if(ch=='-')f=-1;ch=getchar();}12 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}13 return x*f;14 }15 struct edge{16 int v,nxt;17 LL dis;18 }e[mxn*10];19 int hd[mxn],mct=0;20 void add_edge(int u,int v,LL dis){21 e[++mct].v=v;e[mct].nxt=hd[u];e[mct].dis=dis;hd[u]=mct;return;22 }23 int n;24 LL B1,B2;25 LL dis[mxn];26 int a[20];27 bool inq[mxn];28 queue q;29 void SPFA(){30 memset(dis,0x3f,sizeof dis);31 q.push(0);inq[0]=1;dis[0]=0;32 while(!q.empty()){33 int u=q.front();q.pop();inq[u]=0;34 for(int i=hd[u];i;i=e[i].nxt){35 int v=e[i].v;36 if(dis[v]>dis[u]+e[i].dis){37 dis[v]=dis[u]+e[i].dis;38 if(!inq[v]){39 inq[v]=1;40 q.push(v);41 }42 }43 }44 }45 return;46 }47 LL query(LL x){48 LL res=0;49 for(int i=0;i
二:改成了不具体建边的写法,只需要1000+ms
1 #include2 #include 3 #include 4 #include 5 #include 6 #define LL long long 7 using namespace std; 8 const int mxn=500010; 9 int read(){10 int x=0,f=1;char ch=getchar();11 while(ch<'0' || ch>'9'){ if(ch=='-')f=-1;ch=getchar();}12 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}13 return x*f;14 }15 int n;16 LL B1,B2;17 LL dis[mxn];18 int a[20];19 bool inq[mxn];20 queue q;21 void SPFA(){22 memset(dis,0x3f,sizeof dis);23 q.push(0);inq[0]=1;dis[0]=0;24 while(!q.empty()){25 int u=q.front();q.pop();inq[u]=0;26 for(int i=2;i<=n;i++){27 int v=(u+a[i])%a[1];28 if(dis[v]>dis[u]+a[i]){29 dis[v]=dis[u]+a[i];30 if(!inq[v]){31 inq[v]=1;32 q.push(v);33 } 34 }35 }36 }37 return;38 }39 LL query(LL x){40 LL res=0;41 for(int i=0;i