1. 程式人生 > >CQOJ 擴展中國剩余定理 【數論】

CQOJ 擴展中國剩余定理 【數論】

splay queue 分享圖片 因此 cstring exgcd class pan 一般式

原題:

  求在小於等於 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 }
View Code

CQOJ 擴展中國剩余定理 【數論】