Expanding Chinese remainder theorem

Expanding Chinese remainder theorem (EXCRT)

Solutions of solving linear equations of congruence

There are two different methods

CRT and CRT expand

Here focus on what expanding Chinese remainder theorem

Before we set \ (k - 1 \) Solutions of equations is \ (X '\) , \ (M = I = {LCM_. 1} ^ {K -. 1} \)

It is clear that, before the \ (k - 1 \) through the solution of equations
\ [x '+ tM \]
wherein \ (T \) is an arbitrary value

We are now going to solve such a problem
\ [x '+ tM = a_i
\ pmod {b_i} \] then there is
\ [tM + hb_i = a_i-
x' \] This direct \ (excrt \) like

Note that this time we are out of the solution is
\ [tM + hb_i = gcd (
M, b_i) \] solution

So we find \ (t \) after

True \ (T \) should be
\ [t / gcd (M,
b_i) * (a_i-x ') \] so we can directly draw
\ [x = x' + tM
\] Finally, the \ (B_i \) combined \ (M \) just fine on

#include<cstdio>
#include<iostream>
#include<queue>
#include<algorithm>
#include<cstring>
#include<cctype>
#include<vector>
#include<ctime>
#define LL long long
#define pii pair<LL,LL>
#define mk make_pair
#define fi first
#define se second
using namespace std;
const int N = 2e5 + 3;
LL a[N],b[N];
int n;
LL x,y;
inline LL exgcd(LL a,LL b){
    if(b == 0){
        y = 0;
        x = 1;
        return a;
    }
    LL r = exgcd(b,a % b);
    LL t = x;
    x = y;
    y = t - a / b * y;
    return r;
}
inline LL Mul(LL x,LL y,LL mod){
    LL res = 0;
    while(y){
        if(y & 1) res = (res + x) % mod;
        x = (x + x) % mod;
        y = y / 2;
    }
    return res;
}
inline LL excrt(){
    LL M = b[1];LL ans = a[1];
    for(int i = 2;i <= n;++i){
    //  printf("%d %lld %lld\n",i,M,b[i]);
        LL g = exgcd(M,b[i]);
    //  cout << g << endl;
        LL t = (a[i] - ans % b[i] + b[i]) % b[i]; 
        if(t % g != 0) return 0;
        x = Mul(x,t / g,b[i]); 
        ans += x * M;
        M = M * (b[i] / g);
        ans = ((ans % M) + M) % M;
    }
    return ans; 
}
int main(){
//  freopen("A.in","r",stdin);
    scanf("%d",&n);
    for(int i = 1;i <= n;++i) scanf("%lld%lld",&b[i],&a[i]);
    printf("%lld\n",excrt()); 
    return 0;
}   

Also, please note that it may blow up in time of the merger \ (LL \) , so try to take the first addition to the

Guess you like

Origin www.cnblogs.com/wyxdrqc/p/11366507.html