以一个经典例子配合代码来理解:
x%3=2; x%5=3; x%7=2;
1.求最小公倍数:M=3*5*7=105。
2.依照余数求各个数的基础数:
105/3=35,35%3=2;
105/5=21,21%5=1,即63%5=3;
105/7=15,15%7=1,即30%7=2。
3.求和sum=35+63+30=128;
4.求最小满足条件的x=(M+sum%M)%M。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long ll;
//扩展欧几里得,ax+by=gcd(a,b)
ll e_gcd(ll a,ll b,ll &x,ll &y){
if(b==0){
x=1,y=0;
return a;
}
ll res=e_gcd(b,a%b,y,x);
y-=(a/b)*x;
return res;
}
//中国剩余定理,pri[]存放互质的数,r[]存放余数,n为个数
ll china(ll pri[],ll r[],ll n){
ll M=1,m,d,res=0;
for(int i=0;i<n;i++)
M*=pri[i]; //最小公倍数
for(int i=0;i<n;i++){
m=M/pri[i]; //m为除当前这个数不能整除以外都能够被其他数整除,就是其他数的最小公倍数
ll x,y;
d=e_gcd(pri[i],m,x,y); // pri[i]*x+m*y=gcd(pri[i],m]
res=(res+y*m*r[i])%M;
}
return (res%M+M)%M; //满足的最小解
}
ll pri[20],r[20];
int main(){
int n;
while(~scanf("%d",&n)){
for(int i=0;i<n;i++)
scanf("%lld %lld",&pri[i],&r[i]);
ll ans=china(pri,r,n);
printf("%lld\n",ans);
}
}