【模板】扩展中国剩余定理

LUOGU_4777_【模板】扩展中国剩余定理(EXCRT)

请添加图片描述
注意加快速乘,防止整数溢出。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mx=1e5+5;
int n;
ll a[mx],m[mx];
ll fmul(ll x,ll y,ll z) {
	x%=z,y%=z; if(y<0) x=-x,y=-y;
	ll sum(0);
	for(;y;y>>=1) {
		if(y&1) sum=(sum+x)%z;
		x=(x+x)%z; 
	}
	return sum;
}
ll fpow(ll x,ll y,ll z) {
	x%=z;
	ll mul(1);
	for(;y;y>>=1) {
		if(y&1) mul=mul*x%z;
		x=x*x%z;
	}
	return mul;
}
void exgcd(ll &x,ll &y,ll a,ll b,ll &d) {
	if(b==0) {
		x=1,y=0,d=a;
	}
	else {
		exgcd(y,x,b,a%b,d);
		y-=x*(a/b);
	}
}
int main() {
	scanf("%d",&n);
	for(int i=1;i<=n;i++) {
		scanf("%lld%lld",&m[i],&a[i]);
	}
	bool flg(0);
	for(int i=2;i<=n;i++) {
		ll tmp=((a[i]-a[1])%m[i]+m[i])%m[i];
		ll k1,k2,d; exgcd(k1,k2,m[1],m[i],d);
		if(tmp%d) {
			flg=1;break;
		}
		k1=(fmul(k1,tmp/d,m[i]/d)+(m[i]/d))%(m[i]/d);
		ll M=m[1]/d*m[i];
		a[1]=(a[1]+fmul(m[1],k1,M))%M;
		m[1]=M;
	}
	printf("%lld",a[1]);
}

中国剩余定理:
M = ∏ i = 1 n m i M=\prod_{i=1}^nm_i M=i=1nmi M i = M m i M_i=\frac{M}{m_i} Mi=miM ,则 a n s = ∑ i = 1 n M i M i − 1 a i ans=\sum_{i=1}^nM_iM_i^{-1}a_i ans=i=1nMiMi1ai 是模 M M M 意义下原同余方程组的解。其中 M i − 1 M_i^{-1} Mi1 是模 m i m_i mi 意义下的逆元。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mx=1005;
int n;
ll M,res,a[mx],m[mx];
ll fpow(ll x,ll y,ll z) {
	x%=z;
	ll mul(1);
	for(;y;y>>=1) {
		if(y&1) mul=mul*x%z;
		x=x*x%z;
	}
	return mul;
}
void exgcd(ll &x,ll &y,ll a,ll b) {
	if(b==0) {
		x=1,y=0;
	}
	else {
		exgcd(y,x,b,a%b);
		y-=x*(a/b);
	}
}
int main() {
	scanf("%d",&n); M=1;
	for(int i=1;i<=n;i++) {
		scanf("%lld%lld",&m[i],&a[i]);
		M=M*m[i];
	}
	for(int i=1;i<=n;i++) {
		ll mi=M/m[i],x,y;
		exgcd(x,y,mi,m[i]); x=(x%m[i]+m[i])%m[i];
		res=(res+a[i]*mi*x%M)%M;
	}
	printf("%lld",res);
}
posted @ 2021-08-21 10:34  仰望星空的蚂蚁  阅读(14)  评论(0)    收藏  举报  来源