exCRT 学习笔记

exCRT用来求解方程组

\[\begin{cases}x\equiv a_1\pmod {b_1}\\x\equiv a_2\pmod {b_2}\\...\\x\equiv a_n\pmod {b_n}\end{cases} \]

此时不需要满足 \(b_1\text{~}b_n\) 互质

解法:

尝试将 \(n\) 个方程组合并成一个

首先发现:
\(\begin{cases}x\equiv a_1\pmod {b_1}\\x\equiv a_2\pmod {b_2}\\\end{cases}\)

合并之后 \(b\) 一定为 \(lcm(b1,b2)\)

然后考虑 \(a\):

可以发现 \(x=a_1+k_1\times b_1=a_2+k_2\times b_2\)

\(k_1\times b_1-k_2\times b_2=a_2-a_1\)

未知数只有 \(k\) 显然可以exgcd求出(当然如果 \(\gcd(b1,b2)\nmid(a_2-a_1)\) 无解)

然后 \(x=a_1+k_1\times b_1\) 当做合并后的 \(a\) 即可

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inl inline
#define int __int128
#define gc getchar
#define pc putchar
const int N=1e7+5;
const int M=4e2+5;
const int inf=0x7fffffff;
const int mod=1e6+3;
inl int read(){
    int x=0,f=1;char c=gc();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc();}
    while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=gc();}
    return x*f;
}
inl void write(int x){
    if(x<0){pc('-');x=-x;}
    if(x>9)write(x/10);
    pc(x%10+'0');
}
inl void writei(int x){write(x);pc(' ');}
inl void writel(int x){write(x);pc('\n');}
int n,m;
inl void exgcd(int a,int b,int &x,int &y){
    if(!b)return x=1,y=0,void();
    exgcd(b,a%b,y,x);
    y-=(a/b)*x;
}
inl int gcd(int a,int b){return !b?a:gcd(b,a%b);}
inl int lcm(int a,int b){return a*b/gcd(a,b);}
signed main(){
    n=read();
    int b1=read(),a1=read();
    for(int i=2;i<=n;i++){
        int b2=read(),a2=read();
        int d=gcd(b1,b2);
        if((a2-a1)%d){puts("-1");return 0;}
        int x,y;
        exgcd(b1,b2,x,y);
        int mod=lcm(b1,b2);
        a1=(a1+(a2-a1)/d*x%mod*b1%mod+mod)%mod;
        b1=mod;
    }
    writel(a1);
    return 0;
}
posted @ 2023-11-24 17:28  xiang_xiang  阅读(91)  评论(0编辑  收藏  举报