[国家集训队]墨墨的等式(最短路优化完全背包)
题目描述
墨墨突然对等式很感兴趣,他正在研究a_1x_1+a_2x_2+…+a_nx_n=Ba1x1+a2x2+…+anxn=B存在非负整数解的条件,他要求你编写一个程序,给定N、{an}、以及B的取值范围,求出有多少B可以使等式存在非负整数解。
输入格式
输入的第一行包含3个正整数,分别表示N、BMin、BMax分别表示数列的长度、B的下界、B的上界。
输入的第二行包含N个整数,即数列{an}的值。
输出格式
输出一个整数,表示有多少b可以使等式存在非负整数解。
输入输出样例
输入 #12 5 10 3 5输出 #15说明/提示
对于20%的数据,N≤5,1≤BMin≤BMax≤10。
对于40%的数据,N≤10,1≤BMin≤BMax≤106。
对于100%的数据,N≤12,0≤ai≤5∗105,1≤BMin≤BMax≤1012。
十分神奇的思路。
为了优化要选择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 }
We're the lovers above the city.