中国剩余定理
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e2;
typedef long long ll;
/*
中国剩余理论:
*/
ll gcd(ll a,ll b){
return a%b==0?b:gcd(b,a%b);
}//利用辗转相除法求解最大公约数
// 另外c++提供内置函数
// std::__gcd(a,b)
ll lcm(ll a,ll b){
return a/gcd(a,b)*b;
}//求最小公倍数
/*
扩展欧几里得算法:
求 ax+by=n的解:
令a=gcd(a,b)*a’,b=gcd(a,b)*b’
有ax+by=gcd(a,b) *(a’x+b’y)=n
如果x, y, a’, b’都是整数,那么n必须是gcd(a,b)的倍数,才有整数解。
(1)判断ax+by=n有解
(2)用扩展欧几里得求 ax+by=gcd(a,b)的特解(x0, y0)
(3)在ax0+by0=gcd(a,b)的两边同乘n/gcd(a,b),得:
ax0n/gcd(a,b)+by0n/gcd(a,b)=n
(4)对照ax+by=n,一个特解是:
x0' = x0 n /gcd(a,b),
y0'= y0 n /gcd(a,b)
(5)通解:
x=x0+bt
y=y0-at t是任意整数
应用:
(1)求解不定方程;
(2)求解模的逆元;
(3)求解同余方程。
*/
void extend_gcd(ll a,ll b,ll &x,ll &y){//得到特解
if(b==0){
x=1;y=0;
return;
}
extend_gcd(b,a%b,x,y);
ll tmp = x;
x = y;
y = tmp - (a/b)*y;
}
/*
中国剩余定理:
m[]代表质数
a[]代表模数
n:数组的长度
*/
ll rct(ll a[],ll m[],int n){
ll lcm=1;//m[]的最小公倍数,m[]互质
int ans = 0;//中国剩余定理的结果
for(int i=0;i<n;i++)lcm*=m[i];
for(int i=0;i<n;i++){
ll x,y,mi=lcm/m[i];
extend_gcd(mi,m[i],x,y);
ans=(ans+mi*x*a[i])%lcm;
}
return (ans+lcm)%lcm;
}
int main(){
ll a[maxn],m[maxn],n;
cin>>n;
for(int i=0;i<n;i++)cin>>m[i]>>a[i];
cout<<rct(a,m,n);
}
参考博客
中国剩余定理