题目地址: http://acm.hdu.edu.cn/showproblem.php?pid=1573
注意是非互质情况下的中国剩余定理
N===a1(mod r1)
N===a2(mod r2)
以两个为例,则N=a1+r1*x=a2+r2*y,根据后两者就可以建立方程 r1*x-r2*y=a2-a1,扩展欧几里德可搞。
解出x之后 可知N=a1+r1*x,明显这是其中一组解,N+K*(r1*r2)/gcd都是解。
代码如下:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <string> #include <algorithm> #include <vector> #include <set> #include <map> #include <queue> using namespace std; /* freopen("input.txt", "r", stdin); //读数据 freopen("output.txt", "w", stdout); //注释掉此句则输出到控制台 */ int n,m,b[15],w[15]; //扩展Euclid求解gcd(a,b)=ax+by int ext_gcd(int a,int b,int& x,int& y) { int t,ret; if (!b) { x=1,y=0; return a; } ret=ext_gcd(b,a%b,x,y); t=x,x=y,y=t-a/b*y; return ret; } void China_left() { int flag,w1,w2,b1,b2,gcd,x,y,i,t; flag=0;w1=w[0];b1=b[0]; for(i=1;i<m;i++) { w2=w[i];b2=b[i]; gcd=ext_gcd(w1,w2,x,y); if((b2-b1)%gcd) { flag=1;break; } t=w2/gcd; x=(x*(b2-b1))/gcd; x=(x%t+t)%t; b1=w1*x+b1; w1=(w1*w2)/gcd; b1=(b1%w1+w1)%w1; } if(flag||n<b1) printf("0\n"); else printf("%d\n",(n-b1)/w1+1-(b1==0?1:0)); } int main() { int i,j,k,tt; cin>>tt; while(tt--) { cin>>n>>m; for(i=0;i<m;i++) scanf("%d",&w[i]); for(i=0;i<m;i++) scanf("%d",&b[i]); China_left(); } return 0; }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)