CQOJ 扩展中国剩余定理 【数论】
原题:
求在小于等于 n 的正整数中有多少个X满足:
X = b[1] (mod a[1])
X = b[2] (mod a[2])
.....
题解:
对于中国剩余定理的理解:
对于前两式
X=B[1] (mod A[1]) => A[1]*a+B[1]=X
X=B[2] (mod A[2]) => A[2]*b+B[2]=X
两式相减可化为 A[1]*a-A[2]*b=B[2]-B[1]
根据扩展欧几里得(一般式Ax+By=C) 可解得 a , b
又满足二式的X' 有 X'=a*A[1]+B[1] (带入第二式亦可) 且 X'为正整数
则特别的
X‘=x + Lca (x为X'最小取值)
因此二式可合并为 Lca*c+x=X
显而易见,接下来的方程皆可合并直到由最末方程推出最终解
1 /* 2 中国剩余定理 3 */ 4 #include<queue> 5 #include<cstdio> 6 #include<cstring> 7 #include<iostream> 8 #include<algorithm> 9 using namespace std; 10 typedef long long lol; 11 int T; 12 int N,M; 13 lol A[15]; 14 lol B[15]; 15 void Read(lol &x){ 16 x=0; 17 char c=getchar(); 18 while(!isdigit(c)) c=getchar(); 19 while(isdigit(c)) x=x*10-'0'+c,c=getchar(); 20 return ; 21 } 22 lol ExGcd(lol a,lol b,lol &x,lol &y){ 23 if(b==0){ 24 x=1; 25 y=0; 26 return a; 27 } 28 lol xx,yy; 29 lol res=ExGcd(b,a%b,xx,yy); 30 x=yy; 31 y=xx-a/b*yy; 32 return res; 33 } 34 lol Calc(lol a,lol b,lol c,lol &g){ 35 int ok=0; 36 lol x,y; 37 if(a<b) swap(a,b),ok=1; 38 lol res=ExGcd(a,b,x,y); 39 g=abs(res); 40 if(ok) swap(a,b),swap(x,y); 41 x=c/res*x; 42 lol t=abs(b/res); 43 return ((x%t)+t)%t; 44 } 45 void Solve(){ 46 for(int i=1;i<M;i++){ 47 lol g,lc; 48 lol res=Calc(A[i],-A[i+1],B[i+1]-B[i],g); 49 lc=A[i]*A[i+1]/g; 50 A[i+1]=lc; 51 B[i+1]=(res*A[i]+B[i])%lc; 52 } 53 lol ans=(N-B[M])/A[M]; 54 if(B[M]!=0 && B[M]<=N) ans++; 55 cout<<ans<<endl; 56 return ; 57 } 58 void Next_Main(){ 59 scanf("%d%d",&N,&M); 60 for(int i=1;i<=M;i++) 61 Read(A[i]); 62 for(int i=1;i<=M;i++) 63 Read(B[i]); 64 Solve(); 65 return ; 66 } 67 int main(){ 68 scanf("%d",&T); 69 while(T--) Next_Main(); 70 return 0; 71 }