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 }
View Code

 

posted @ 2018-07-11 20:47  Wannabtl  阅读(835)  评论(0编辑  收藏  举报