给定 n n n个同余式, m 1 , m 2 . . . , m n m_1,m_2...,m_n m1,m2...,mn不一定互质
问,满足上述同余式最小的 x x x是多少
显然不能再用CRT的方法来求解了
那么我们考虑逐一进行求解
假设当前已经求出前 k − 1 k-1 k−1个方程组的解,记为 x x x
且有 M = ∏ i = 1 k − 1 m i M=\prod_{i=1}^{k-1}m_i M=∏i=1k−1mi
那么前k-1个方程组的同解即为 x + i ∗ M , i ∈ Z x+i*M,i\in Z x+i∗M,i∈Z
那么对于当前加入的第 k k k个方程组,我们其实就是需要找到一个 t t t,使得 x + t ∗ M ≡ a k ( m o d m k ) x+t*M\equiv a_k\pmod{m_k} x+t∗M≡ak(modmk)
稍微转化一下这个式子 ⇒ t ∗ M ≡ a k − x ( m o d m k ) \Rightarrow t*M\equiv{a_k-x}\pmod{m_k} ⇒t∗M≡ak−x(modmk)
那么就可以用拓欧来解决这个式子了,如果该方程无解,那么整个方程组无解,否则继续解下去
可以发现EXCRT的本质就是求解n次拓展欧几里得
#include
#define int long long
using namespace std;
int read(){
int f=1,re=0;char ch;
for(ch=getchar();!isdigit(ch)&&ch!='-';ch=getchar());
if(ch=='-'){
f=-1,ch=getchar();}
for(;isdigit(ch);ch=getchar()) re=(re<<3)+(re<<1)+ch-'0';
return re*f;
}
int k,a[100009],b[100009];
int ksm(int a,int b,int mod){
int ans=1;
while(b){
if(b&1) ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}return ans;
}
int qmul(int a,int b,int mod){
int ans=0;
while(b){
if(b&1) ans=(ans+a)%mod;
a=(a+a)%mod;
b>>=1;
}return ans;
}
int exgcd(int a,int b,int &x,int &y){
if(b==0){
x=1,y=0;return a;}
int d=exgcd(b,a%b,x,y);
int tmp=x;
x=y,y=tmp-a/b*y;
return d;
}
int excrt(){
int ans=b[1],lcm=a[1],x,y;
for(int i=2;i<=k;i++){
int c=(b[i]-ans%a[i]+a[i])%a[i];
int d=exgcd(lcm,a[i],x,y);
if(c%d) return -1;
int r=a[i]/d;
x=qmul(x,c/d,r);
ans+=x*lcm;
lcm*=r;
ans=(ans%lcm+lcm)%lcm;
}return ans=(ans%lcm+lcm)%lcm;
}
signed main(){
k=read();
for(int i=1;i<=k;i++) a[i]=read(),b[i]=read();
printf("%lld\n",excrt());
return 0;
}