𝐶𝑅𝑇:𝐶ℎ𝑖𝑛𝑒𝑠𝑒 𝑅𝑒𝑚𝑎𝑖𝑛𝑑𝑒𝑟 𝑇ℎ𝑒𝑜𝑟𝑒:
今有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二,问物几何?(古人都比我们聪明)
因此求形如:
\(x \equiv r_1 \quad (mod \, p_1)\)
\(x \equiv r_2 \quad (mod \, p_2)\)
...
\(x \equiv r_n \quad (mod \, p_n)\)
的解x?
但能使用CRT的前提是:对于任意 \(i,j \quad gcd(i,j)=1\) (所有模数互质)
算法流程
1.\(m\)为所有\(P_i\)的乘积
2.对于第\(i\)个方程式,我们给 \(ans+=m/p_i*inv(m/p_i,p_i)*r_i\)
因为\(m/p_i\)表示\(m/a[i]\)满足为除了i以外所有数的倍数,且 \(m/a[i]*k \equiv 1 \quad (mod \, a[i])\)
代码:
#include<stdio.h>
#include<bits/stdc++.h>
using namespace std;
const int N=15;
typedef long long ll;
ll a[N],b[N];
ll ex_gcd(ll a,ll b,ll &x,ll &y) { //a>b
if(b==0) {
x=1,y=0; return a;
}
ll d=ex_gcd(b,a%b,x,y);
ll xx=x; x=y; y=xx-a/b*y;
}
ll inv(ll a,ll p) {
ll x=1ll,y=0ll;
ll d=ex_gcd(a,p,x,y);
return x;
}
int main() {
int n;
ll m=1ll,ans=0;
scanf("%d",&n);
for(int i=1;i<=n;i++) {
scanf("%lld%lld",&a[i],&b[i]); //模数,余数
m*=a[i];
}
for(int i=1;i<=n;i++) {
ans=(ans+(m/a[i])%m*inv(m/a[i],a[i])%m*b[i]%m)%m; //m/a[i]满足为除了i以外所有数的倍数,且m/a[i]*k=1(mod a[i])
}
printf("%lld",ans>0?ans:ans+m);
return 0;
}