中国剩余定理

中国剩余定理

问题:

已知 \(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;
}
posted @ 2025-05-10 15:56  ___jungle  阅读(31)  评论(0)    收藏  举报