中国剩余定理
中国剩余定理
问题:
已知 \(a_1\sim a_n\) \(b_1\sim b_n\) 求最小的自然数 \(x\) 使得:
\[\left\{\begin{matrix}
x\equiv b_1(\bmod a_1)\\
x\equiv b_2(\bmod a_2)\\
\dots \\
x\equiv b_n(\bmod a_n)
\end{matrix}\right.\]
思路
只要求出一个答案,对于 \(\prod b\) 取模即可。
考虑\(x_1\sim x_n\),使得:
\[\left\{\begin{matrix}
x_i\equiv 0(\bmod a_1)\\
\dots \\
x_i\equiv 1(\bmod a_i)\\
\dots \\
x_i\equiv 0(\bmod a_n)
\end{matrix}\right.
\]
\[x=\sum x_ib_i
\]
而注意到 $\frac{\prod a}{a_i} \mid x_i $ ,所以问题转化为:
求 \(\frac{\prod a}{a_i}\) 在模 \(a_i\) 意义上的逆元, $$x_i = \frac{\prod b}{b_i} \cdot \frac{1}{\frac{\prod b}{b_i}}$$
用Exgcd求解。
代码
点击查看代码
#include<bits/stdc++.h>
using namespace std;
__int128 n,p,t,tt;__int128 ans,ttt,temp=1ull,a[11],b[11],x;
void exgcd(__int128 a,__int128 b,__int128 &x,__int128 &y){
if(b==0){
x=1;
y=0;
}
else {
exgcd(b,a%b,y,x);
y-=a/b*x;
}
}
inline void read(__int128 &n){
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
n=x*f;
}
inline void print(__int128 n){
if(n<0){
putchar('-');
n*=-1;
}
if(n>9) print(n/10);
putchar(n % 10 + '0');
}
int main(){
read(n);
for(int i=0;i<n;i++){
read(a[i]);read(b[i]);
temp *= a[i];
}
for(__int128 i=0;i<n;i++){
t=0;tt=0;
exgcd(temp/a[i],a[i],t,tt);
while(t<0) t+=a[i];ttt=t;
// cout<<ttt<<'\n';
x= ((temp/a[i]) * b[i]%temp*ttt%temp);
while(x<0) x+=temp;
ans+=x;
ans%=temp;
}
print(ans);
return 0;
}

浙公网安备 33010602011771号