ExCRT
求
\[\begin{cases}
x\equiv a_1\pmod{m_1}\\
x\equiv a_2\pmod{m_2}\\
\vdots\\
x\equiv a_n\pmod{m_n}
\end{cases}
\]
的一个任意解。
以上是 ExCRT解决的问题。
https://www.luogu.com.cn/problem/P4777
- 递归:利用 exgcd 合并 i-1,i 方程
- 最后剩下的方程的 \(a_n\) 稍加取模得到答案
如何使用 exgcd 合并方程
\[\begin{cases}
x\equiv a_1\pmod{m_1}\\
x\equiv a_2\pmod{m_2}
\end{cases},\\
x=k_1m_1+a_1=k_2m_2+a_2,\\
m_1k_1-m_2k_2=a_2-a_1.
\]
显然使用 exgcd 求解↑。
将 \(k_1/k_2\) 回带得 \(x\) 的一个任意解。
不难发现通解 \(x\equiv x^*\pmod {\operatorname{lcm}(m_1,m_2)}\)(\(x^*\) 代表特解)。
注意事项
- 龟速乘——可能
1e18*1e18 - 及时取模——模数不同,不能留负数
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+5;
int n;
pair<int,int>a[N];
int exgcd(int a,int b,int &x,int &y){
if(!b){x=1,y=0;return a;}
int d=exgcd(b,a%b,x,y),x1=x,y1=y;
x=y1,y=x1-a/b*y1;
return d;
}
int mul(int a,int b,int mod){
int c=0;
while(b){
if(b%2)c=(c+a)%mod;
a=(a+a)%mod,b/=2;
}
return (c+mod)%mod;
}
pair<int,int>work(pair<int,int>a,pair<int,int>b){
pair<int,int>c;
int x,y,A=a.second,B=-b.second,C=b.first-a.first,d=exgcd(A,B,x,y),l=abs(a.second/d*b.second);
if(C%d)return make_pair(-1,-1);
C/=d,x=mul(C,x,l);
return make_pair(((mul(a.second,x,l)+a.first)%l+l)%l,l);
}
signed main(){
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i].second>>a[i].first;
for(int i=2;i<=n;i++)a[i]=work(a[i-1],a[i]);
cout<<(a[n].first?a[n].first:a[n].second);
}

浙公网安备 33010602011771号