CRT学习笔记
CRT用来求解方程组
\[\begin{cases}x\equiv a_1\pmod {b_1}\\x\equiv a_2\pmod {b_2}\\...\\x\equiv a_n\pmod {b_n}\end{cases}
\]
需满足条件: \(b_1,b_2,...,b_n\) 互质
解法:
设 \(tot=\prod_{i=1}^nb_i\quad m_i=\dfrac{tot}{b_i}\)
对于每一个 $i\ $ 解方程 \(m_ik_i\equiv1\pmod {b_i}\) 得到 \(k_i\) (不会解的看这里)
(若\(b_1,b_2,...,b_n\) 不互质 必然无解)
令 $x_i=m_ik_ia_i\ $
我们发现 \(m_ik_ia_i\equiv a_i\pmod {b_i}\) 且 \(x\) 为所有 \({b_j}(j\ne i)\)的倍数
我们能得到 \(x_i\equiv a_i\pmod {b_i}\) 且 \(x_i\equiv0\pmod {b_j}(j\ne i)\)
设 \(ans=\sum_{i=1}^nx_i\)
则 \(ans\) 为方程的解
code:
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define inl inline
#define ll long long
const int N=1e5+5;
inl ll read(){
ll x=0,f=1;char c=getchar();
while(c<'0'|c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return x*f;
}
ll n,a[N],b[N],x,y,tot=1,ans;
void exgcd(ll a,ll b,ll &x,ll &y){
if(b==0){
x=1;y=0;
return;
}
exgcd(b,a%b,y,x);
y-=(a/b)*x;
}
int main(){
n=read();
for(int i=1;i<=n;i++){
b[i]=read();a[i]=read();
tot*=b[i];
}
for(int i=1;i<=n;i++){
ll mi=tot/b[i];
exgcd(mi,b[i],x,y);
x=(x%b[i]+b[i])%b[i];
x=mi*x*a[i]%tot;
ans=(ans+x)%tot;
}
printf("%lld\n",ans);
return 0;
}