【模板】中国剩余定理解同余方程(附_int128)

//问题:求解同余方程组
// x ≡ a1 (mod b1)
// x ≡ a2 (mod b2)
// x ≡ a3 (mod b3)
//  ······
// x ≡ an (mod bn)
//其中b1,b2,b3,······ bn 为不一定两两互质的整数,求x的最小非负整数

//模板
#include
#define up(i, x, y) for(__int128 i = x; i <= y; i++)
#define down(i, x, y) for(__int128 i = x; i >= y; i--)
#define maxn ((int)1000 + 10)
#define INF 0x3f3f3f3f
using namespace std;


__int128 n, ai[maxn], bi[maxn];// bi存余数

__int128 exgcd(__int128 a, __int128 b, __int128 &x, __int128 &y)
{
    if(!b){ x = 1; y = 0; return a;}
    __int128 gcd = exgcd(b, a % b, x, y);
    __int128 t = x; x = y;
    y = t - a / b * y;
    return gcd;
}

__int128 excrt()
{
    __int128 x, y, k;
    __int128 M = bi[1], ans = ai[1];//第一个方程的解特判
    for(__int128 i = 2; i <= n; i++)
    {
        __int128 a = M, b = bi[i], c = (ai[i] - ans % b + b) % b;//ax≡c(mod b)
        __int128 gcd = exgcd(a, b, x, y), bg = b / gcd;
        if(c % gcd != 0) return -1;//判断是否无解
        x = (x * (c / gcd) % bg);
        ans += x * M;//更新前k个方程组的答案
        M *= bg;//M为前k个m的lcm
        ans = (ans % M + M) % M;
    }
    return (ans % M + M) % M;
}
__int128 f[maxn];

inline __int128 read()
{
    __int128 x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*f;
}

inline void write(__int128 x)
{
    if(x<0)
    {
        putchar('-');
        x=-x;
    }
    if(x>9)
        write(x/10);
    putchar(x%10+'0');
}

int main()
{
    init();
    n = read();
    for(__int128 i = 1; i <= n; i++)
         bi[i] = read(),  ai[i] = read() ;
    __int128 ans = excrt();
    write(ans);
    return 0;
}

你可能感兴趣的:(数论,模板)