Chinese remainder theorem (solving a linear congruence equation) Chinese remainder theorem (solving a linear congruence equation)

Chinese remainder theorem (solving a linear congruence equation)

 

problem:

  There is such a problem in the "Sun Tzu Suan Jing" said: "Today there was an unknown number three number three of the remaining two (remainder divided by 32), fifty-five number of remaining three (3 divided by more than 5) Weeks the number of the remaining two (divided by more than 72), asked the geometric objects? "this problem is called" grandson problem ", called on the international general solution to the problem," Chinese remainder Theorem. "

Resolution:

  The meaning is the subject of such a set of equations:

(M1 --- mn pairwise mass)

 

 

 Assume:

 

 

 Assume:

 

 

 Set up:   So:

 

 

 So the equation is solvable:

 

 

 Find modM meaning under, or the smallest positive integer solution: the equation has a unique solution:

Note: Assuming an integer of m1, m2, m3 ... mn pairwise mass, then for any integer a1, a2, a3 ... an, x solvability

Example:

for

x % 3 = 2

x % 5 = 3

x % 7 = 2

We need to construct an answer // inv is the inverse yuan

5*7*inv(5*7,  3) % 3  =  1

3*7*inv(3*7,  5) % 5  =  1

3*5*inv(3*5,  7) % 7  =  1 

Then take sides with the number you need, too

2 * 5*7*inv(5*7,  3) % 3  =  2

3 * 3*7*inv(3*7,  5) % 5  =  3

2 * 3*5*inv(3*5,  7) % 7  =  2

make 

a = 2 * 5*7*inv(5*7,  3) 

b = 3 * 3*7*inv(3*7,  5) 

c = 2 * 3*5*inv(3*5,  7) 

Then

a % 3 = 2

b % 5 = 3

c % 7 = 2

The answer is a + b + c

because

a% 5 = a% 7 = 0 // a is a multiple of 5 * 7 * inv (5 * 7,3), so the mold 5 and 7 are

b% 3 = b% 7 = 0 // Similarly, b, c mold 3 / 7,3 / 5 are all 0

c%3 = c%5 = 0 

and so

(a + b + c) % 3 = (a % 3) + (b % 3) + (c % 3) = 2 + 0 + 0 = 2

(a + b + c) % 5 = (a % 5) + (b % 5) + (c % 5) = 0 + 3 + 0 = 3

(a + b + c) % 7 = (a % 7) + (b % 7) + (c % 7) = 0 + 0 + 2 = 2

I.e., a + b + c is a number satisfying the condition to give @ answer smallest positive integer solution is obtained (a + b + c)% 105 (105 = 3 * 5 * 7, pairwise nature, the least common multiple of 105)

Code:

Copy the code
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <cstdio>
#include <queue>
#include <cmath>
#include <map>
#include <set>

using namespace std;

typedef long long ll;

const int maxn=1e5+10;

ll a[maxn],m[maxn],n;

ll ex_gcd(ll a,ll b,ll &x,ll &y){
    if(b==0){x=1;y=0;return a;}
    ll ans=ex_gcd(b,a%b,x,y);
    ll temp=x;
    x=y;
    y=temp-a/b*y;
    return ans;
}
ll inv(ll a,ll b){   //求逆
   ll x,y;
   ll ans=ex_gcd(a,b,x,y);
   if(ans!=1)return -1;
   if(x<0)x=(x%b+b)%b;
   return x;
}
ll China(){//中国剩余定理
   ll M=1;
   for(int i = 0;i<n;i++){
      M*=m[i];
   }
   ll sum=0;
   for(int i=0;i<n;i++){
      ll res=M/m[i];
      sum=(sum+a[i]*res*inv(res,m[i]))%M;
   }
   return sum;
}

int main(){
    while(scanf("%lld",&n)!=EOF){
        for(int i=0;i<n;i++){
            scanf("%lld%lld",&m[i],&a[i]);
        }
        ll ans=China();
        printf("%lld\n",ans);
    }
    return 0;
}
Copy the code

The above methods can only solve m twenty-two congruence equation relatively prime, if not relatively prime it?

Act One:

Assuming that only two equations, if they can use an equation instead of two equations, and can get the solution of this equation, then the problem is solved:

x=a1+ k1*b1 (x%b1= a1)

x=a2+ k2*b2 (x%b2 = a2)

Then: a1l + k1 * b1 = a2 + k2 * b2

then: b1* k1 + b2*(-k2)= a2-a1

Suppose gcd (b1, b2) = g if (a2 - a1)% g = 0:! No solution

Otherwise: k1 * b1 = (a2-a1) + k2 * b2

then: k1*b1/g = (a2-a1)/g + k2*b2/g

then: k1*b1/g = (a2-a1)/g (mod b2/g)

then : k1 = inv(b1/g,b2/g)*(a2-a1)/g (mod b2/g)

then:x = a1 + inv(b1/g,b2/g)*(a2-a1)/g*b1 + b2*b1/g*y

then :x = c(mod m)

中:c= a1 + inv(b1/g,b2/g)*(a2-a1)/g*b1

m= b1*b2/g = lcm(b1,b2)

As a new equation simultaneous continue with the next, until the last remaining equation xn = cn (mod mn) then,

 

A solution of any of the conditions are satisfied xn, can take the smallest positive integer ans = (cn% mn + mn)% mn

Code:

Copy the code
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <cstdio>
#include <queue>
#include <cmath>
#include <map>
#include <set>

using namespace std;

typedef long long ll;
const int maxn=1e5+10;
ll C[maxn],M[maxn];
ll n,k;
ll gcd(ll a,ll b){
    return b==0?a:gcd(b,a%b);
}
ll ex_gcd(ll a,ll b,ll &x,ll &y){
    if(b==0){x=1;y=0;return a;}
    ll g=ex_gcd(b,a%b,x,y);
    ll temp=x;
    x=y;
    y=temp-a/b*y;
    return g;
}
ll inv(ll a,ll mod){
    ll X,Y;
    ll g=ex_gcd(a,mod,X,Y);
    if(g!=1)return -1;
    return (X%mod+mod)%mod;
}
/*
ll mul(ll a,ll b,ll mod){   //快速乘法
    ll ans=0;
    while(b){
        if(b&1)ans=(ans%mod+a%mod)%mod;
        b>>=1;
        a=(a%mod+a%mod)%mod;
    }
    return ans;
}
*/
int main(){
    while(scanf("%lld",&n)!=EOF){
        for(int i = 0;i<n;i++){
            scanf("%lld%lld",&M[i],&C[i]);
        }
        bool flag=true;
        for(int i=1;i<n;i++){
            ll M1=M[i-1],M2=M[i],C1=C[i-1],C2=C[i];
            ll g=gcd(M1,M2);
            if((C2-C1)%g){flag = false;break;}
            M[i]=M1/g*M2;   //可能会爆
            ll INV=inv(M1/g,M2/g);
            if(INV==-1){flag=false;break;}
            C[i]= C1+(INV*((C2-C1)/g))%(M2/g)*M1;
            C[i]=(C[i]%M[i]+M[i])%M[i];
        }
        if(!flag)printf("-1\n");
        else printf("%lld\n",C[n-1]);
    }
    return 0;
}
Copy the code

Act II :( m only a relatively small time / cow off the 2019 summer school more than 1-d)

Note that before the configuration of i equations minimum natural number solution, before assuming the minimum natural number i-1 th equation is f (i-1). lcm (p1, p2, ......, pi-1) = y, so that f (i) = f (i-1) and let f (i) each plus y, the i-th known equations can be satisfied. In the case of guarantee can prove solvability, adding no more than pi times. (It first determines whether or solutions of equations)

 

problem:

  There is such a problem in the "Sun Tzu Suan Jing" said: "Today there was an unknown number three number three of the remaining two (remainder divided by 32), fifty-five number of remaining three (3 divided by more than 5) Weeks the number of the remaining two (divided by more than 72), asked the geometric objects? "this problem is called" grandson problem ", called on the international general solution to the problem," Chinese remainder Theorem. "

Resolution:

  The meaning is the subject of such a set of equations:

(M1 --- mn pairwise mass)

 

 

 Assume:

 

 

 Assume:

 

 

 Set up:   So:

 

 

 So the equation is solvable:

 

 

 Find modM meaning under, or the smallest positive integer solution: the equation has a unique solution:

注释:假设整数m1,m2,m3...mn两两互质,则对于任意整数a1,a2,a3...an,x有解

例:

对于

x % 3 = 2

x % 5 = 3

x % 7 = 2

我们需要构造一个答案         //inv为求逆元

5*7*inv(5*7,  3) % 3  =  1

3*7*inv(3*7,  5) % 5  =  1

3*5*inv(3*5,  7) % 7  =  1 

然后两边同乘你需要的数,得

2 * 5*7*inv(5*7,  3) % 3  =  2

3 * 3*7*inv(3*7,  5) % 5  =  3

2 * 3*5*inv(3*5,  7) % 7  =  2

令 

a = 2 * 5*7*inv(5*7,  3) 

b = 3 * 3*7*inv(3*7,  5) 

c = 2 * 3*5*inv(3*5,  7) 

那么

a % 3 = 2

b % 5 = 3

c % 7 = 2

其实答案就是a+b+c

因为

a%5 = a%7 = 0 //a是5*7*inv(5*7,3)的倍数,所以模5和7都是

b%3 = b%7 = 0 //同理,b,c模3/7,3/5都是0

c%3 = c%5 = 0 

所以

(a + b + c) % 3 = (a % 3) + (b % 3) + (c % 3) = 2 + 0 + 0 = 2

(a + b + c) % 5 = (a % 5) + (b % 5) + (c % 5) = 0 + 3 + 0 = 3

(a + b + c) % 7 = (a % 7) + (b % 7) + (c % 7) = 0 + 0 + 2 = 2

即a+b+c是一个满足条件得答案      //最小得正整数解为(a+b+c)%105(105=3*5*7,两两互质,105为最小公倍数)

代码:

Copy the code
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <cstdio>
#include <queue>
#include <cmath>
#include <map>
#include <set>

using namespace std;

typedef long long ll;

const int maxn=1e5+10;

ll a[maxn],m[maxn],n;

ll ex_gcd(ll a,ll b,ll &x,ll &y){
    if(b==0){x=1;y=0;return a;}
    ll ans=ex_gcd(b,a%b,x,y);
    ll temp=x;
    x=y;
    y=temp-a/b*y;
    return ans;
}
ll inv(ll a,ll b){   //求逆
   ll x,y;
   ll ans=ex_gcd(a,b,x,y);
   if(ans!=1)return -1;
   if(x<0)x=(x%b+b)%b;
   return x;
}
ll China(){//中国剩余定理
   ll M=1;
   for(int i = 0;i<n;i++){
      M*=m[i];
   }
   ll sum=0;
   for(int i=0;i<n;i++){
      ll res=M/m[i];
      sum=(sum+a[i]*res*inv(res,m[i]))%M;
   }
   return sum;
}

int main(){
    while(scanf("%lld",&n)!=EOF){
        for(int i=0;i<n;i++){
            scanf("%lld%lld",&m[i],&a[i]);
        }
        ll ans=China();
        printf("%lld\n",ans);
    }
    return 0;
}
Copy the code

上述方法只能解决m两两互质的同余方程组,如果不互质呢?

法一:

假设只有两个方程,如果能用一个方程代替两个方程,并能得到这个方程的解,那么这个问题就解决了:

x=a1+ k1*b1 (x%b1= a1)

x=a2+ k2*b2 (x%b2 = a2)

则: a1l+ k1*b1= a2 + k2*b2

then: b1* k1 + b2*(-k2)= a2-a1

假设gcd(b1,b2)= g若(a2 - a1)%g!=0 :无解

否则:k1*b1= (a2-a1) + k2*b2

then: k1*b1/g = (a2-a1)/g + k2*b2/g

then: k1*b1/g = (a2-a1)/g (mod b2/g)

then : k1 = inv(b1/g,b2/g)*(a2-a1)/g (mod b2/g)

then:x = a1 + inv(b1/g,b2/g)*(a2-a1)/g*b1 + b2*b1/g*y

then :x = c(mod m)

中:c= a1 + inv(b1/g,b2/g)*(a2-a1)/g*b1

m= b1*b2/g = lcm(b1,b2)

当作一个新方程继续与下一个联立,直到剩下最后一个方程xn = cn(mod mn)则,

 

任意一个xn都是满足条件的解,取最小正整数即可ans = (cn%mn + mn)%mn

代码:

Copy the code
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <cstdio>
#include <queue>
#include <cmath>
#include <map>
#include <set>

using namespace std;

typedef long long ll;
const int maxn=1e5+10;
ll C[maxn],M[maxn];
ll n,k;
ll gcd(ll a,ll b){
    return b==0?a:gcd(b,a%b);
}
ll ex_gcd(ll a,ll b,ll &x,ll &y){
    if(b==0){x=1;y=0;return a;}
    ll g=ex_gcd(b,a%b,x,y);
    ll temp=x;
    x=y;
    y=temp-a/b*y;
    return g;
}
ll inv(ll a,ll mod){
    ll X,Y;
    ll g=ex_gcd(a,mod,X,Y);
    if(g!=1)return -1;
    return (X%mod+mod)%mod;
}
/*
ll mul(ll a,ll b,ll mod){   //快速乘法
    ll ans=0;
    while(b){
        if(b&1)ans=(ans%mod+a%mod)%mod;
        b>>=1;
        a=(a%mod+a%mod)%mod;
    }
    return ans;
}
*/
int main(){
    while(scanf("%lld",&n)!=EOF){
        for(int i = 0;i<n;i++){
            scanf("%lld%lld",&M[i],&C[i]);
        }
        bool flag=true;
        for(int i=1;i<n;i++){
            ll M1=M[i-1],M2=M[i],C1=C[i-1],C2=C[i];
            ll g=gcd(M1,M2);
            if((C2-C1)%g){flag = false;break;}
            M[i]=M1/g*M2;   //可能会爆
            ll INV=inv(M1/g,M2/g);
            if(INV==-1){flag=false;break;}
            C[i]= C1+(INV*((C2-C1)/g))%(M2/g)*M1;
            C[i]=(C[i]%M[i]+M[i])%M[i];
        }
        if(!flag)printf("-1\n");
        else printf("%lld\n",C[n-1]);
    }
    return 0;
}
Copy the code

Act II :( m only a relatively small time / cow off the 2019 summer school more than 1-d)

Note that before the configuration of i equations minimum natural number solution, before assuming the minimum natural number i-1 th equation is f (i-1). lcm (p1, p2, ......, pi-1) = y, so that f (i) = f (i-1) and let f (i) each plus y, the i-th known equations can be satisfied. In the case of guarantee can prove solvability, adding no more than pi times. (It first determines whether or solutions of equations)

 

Guess you like

Origin www.cnblogs.com/vxcvxvxvdfgdfg/p/12071069.html