洛谷P4777 【模板】扩展中国剩余定理(EXCRT)

题外话:这次同步赛Day2 P1考到了exCRT,去网上拉了个错误的板子一个小时都没调出来。

所以。。。我来刷了一道板子题。

题意

给定线性模方程组

$$\begin{cases} x \equiv b_1\ ({\rm mod}\ a_1) \\ x\equiv b_2\ ({\rm mod}\ a_2) \\ ... \\ x \equiv b_n\ ({\rm mod}\ a_n)\end{cases}$$

求$x$的最小正整数解

题解

一道板子好题。

直接上代码:

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
ll n; ll a[100055], b[100055];

/***************** BAN ZI START ******************/
ll readint() {
    ll ret; scanf(LL, &ret); return ret;
}
inline ll MulMod(ll a, ll b, ll m){
    ll t = a * b - (ll)((long double)a * b / m + 1e-10) * m;
    return (t %= m) < 0 ? t + m : t;
}
ll exgcd(ll a,ll b,ll &x,ll &y){
    if(b==0){
        x=1,y=0;return a;
    }
    ll ret=exgcd(b,a%b,y,x);
    y-=(a/b)*x;
    return ret;
}
ll excrt(ll*r,ll*a,int n){
    ll M=a[1],R=r[1],x,y,d;
    for(int i=2;i<=n;i++){
        d=exgcd(M,a[i],x,y);
        x=MulMod((R-r[i])/d, x, a[i]);
        R -= M*x;
        M = M/d * a[i];
    }
    return (R%M+M)%M;
}
/***************** BAN ZI END ******************/

int main() {
    n = readint();
    for (int i=1; i<=n; i++) b[i] = readint(), a[i] = readint();
    ll ans = excrt(a, b, n);
    printf("%lld\n", ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/mchmch/p/luogu-p4777.html