BZOJ2118: 墨墨的等式
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2118
题解:考虑模某个数意义下x是否能达到。用最小的数作为模数,那么只要建图跑最短路就可以统计答案了。
代码:
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 #include<iostream> 7 #include<vector> 8 #include<map> 9 #include<set> 10 #include<queue> 11 #include<string> 12 #define inf 1000000000000ll 13 #define maxn 500000+5 14 #define maxm 8000000+5 15 #define eps 1e-10 16 #define ll long long 17 #define pa pair<int,int> 18 #define for0(i,n) for(int i=0;i<=(n);i++) 19 #define for1(i,n) for(int i=1;i<=(n);i++) 20 #define for2(i,x,y) for(int i=(x);i<=(y);i++) 21 #define for3(i,x,y) for(int i=(x);i>=(y);i--) 22 #define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go) 23 #define mod 1000000007 24 #define lch t[k].l,l,mid 25 #define rch t[k].r,mid+1,r 26 using namespace std; 27 inline ll read() 28 { 29 ll x=0,f=1;char ch=getchar(); 30 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 31 while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();} 32 return x*f; 33 } 34 int n,head[maxn],mx=1000000,tot,a[maxn]; 35 ll l,r,d[maxn]; 36 bool v[maxn]; 37 queue<int>q; 38 struct edge{int go,next,w;}e[maxm]; 39 inline void add(int x,int y,int w) 40 { 41 e[++tot]=(edge){y,head[x],w};head[x]=tot; 42 } 43 inline ll work(ll x,ll y,ll z) 44 { 45 return x<y?0:(x-y)/z+1; 46 } 47 int main() 48 { 49 freopen("input.txt","r",stdin); 50 freopen("output.txt","w",stdout); 51 n=read();l=read();r=read(); 52 for1(i,n)a[i]=read(),mx=min(mx,a[i]); 53 for1(i,n)for0(j,mx-1)add(j,(j+a[i])%mx,a[i]); 54 for0(i,mx-1)d[i]=inf; 55 d[0]=0;q.push(0); 56 while(!q.empty()) 57 { 58 int x=q.front();q.pop();v[x]=0; 59 for4(i,x)if(d[x]+e[i].w<d[y]) 60 { 61 d[y]=d[x]+(ll)e[i].w; 62 if(!v[y]){v[y]=1;q.push(y);} 63 } 64 } 65 ll ans=0; 66 for0(i,mx-1)ans+=work(r,d[i],mx)-work(l-1,d[i],mx); 67 cout<<ans<<endl; 68 return 0; 69 }