思路
中国剩余定理解决的是这样的问题
求x满足
[egin{matrix}x equiv a_1(mod m_1)\xequiv a_2(mod m_2)\ dots\xequiv a_n(mod m_n)end{matrix}
]
在模数互质的情况下,解为
[x=sum_ia_iM_iM_i^{-1}(mod M)
]
其中(M=prod_{i}m_i),(M_i=frac{M}{m_i}),(M_i^{-1})为(M_i)在模(m_i)意义下的逆元
在模数不互质的情况下,我们需要扩展中国剩余定理
设有两个同余方程
[x equiv a_1(mod m_1)\xequiv a_2 (mod m_2)
]
其中(m_1)与(m_2)不互质
可得到
[x=a_1+m_1x_1\
x=a_2+m_2x_2
]
所以得到
[a_1+m_1x_1 = a_2+m_2x_2
]
变形后有
[m_1x_1+m_2x_2=a_2-a_1
]
用exgcd解出最小的(x_1)
则有
[x equiv (a_1+m_1x_1)(mod lcm(m_1,m_2))
]
相当于把两个式子合并在一起,EXcrt就是将所有式子合并完即可
代码
因为不想写龟速乘所以用了__int128
#include <cstdio>
#include <algorithm>
#include <cstring>
#define int __int128
using namespace std;
int exgcd(int a,int b,int &x,int &y){
if(b==0){
x=1,y=0;
return a;
}
int req=exgcd(b,a%b,x,y);
int t=x;
x=y;
y=t-a/b*y;
return req;
}
int gcd(int a,int b){
return (b==0)?a:gcd(b,a%b);
}
int lcm(int a,int b){
return (a*b)/gcd(a,b);
}
int calc(int a,int b,int c){//ax+by=c
int d=gcd(a,b);
int x1,x2;
exgcd(a,b,x1,x2);
b/=d;
x=(x*(c/d)%b+b)%b;
return ans;
}
pair<int,int> merge(int a1,int m1,int a2,int m2){
int x1=calc(m1,m2,a2-a1);
return make_pair(x1*m1+a1,lcm(m1,m2));
}
int n,a[100100],m[100100];
signed main(){
long long mx;
scanf("%lld",&mx);
n=mx;
for(int i=1;i<=n;i++){
scanf("%lld",&mx);
m[i]=mx;
scanf("%lld",&mx);
a[i]=mx;
}
int mida=a[1],midm=m[1];
for(int i=1;i<n;i++){
pair<int,int> t= merge(mida,midm,a[i+1],m[i+1]);
mida=t.first;
midm=t.second;
}
printf("%lld
",(long long)mida);
return 0;
}