中国剩余定理及扩展模板

m互质的情况:中国剩余定理
洛谷 P3868 [TJOI2009]猜数字
数据比较卡,所以要优化一点.

#include<cstdio>
typedef long long ll;
const ll mod=1e18+7;
ll qmul(ll a,ll b,ll mod){
    ll ans=0;
    while(b>0){
        if(b&1) ans=(ans+a)%mod;
        a=(a+a)%mod;
        b>>=1;
    }
    return 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(){
	ll a[100],b[100];
	ll k;
	scanf("%lld",&k);
	ll res=0,M=1;
	for(int i=0;i<k;i++)
		scanf("%lld",&a[i]);
	for(int i=0;i<k;i++){
		scanf("%lld",&b[i]);
		M*=b[i];
	}
	for(int i=0;i<k;i++) a[i]=(a[i]%b[i]+b[i])%b[i];
	for(int i=0;i<k;i++){
		ll mm=M/b[i],x,y;
		exgcd(mm,b[i],x,y);
		x=(x%b[i]+b[i])%b[i];
		res=(res+qmul(qmul(mm,x,M),a[i],M))%M;
	}
	printf("%lld\n",(res%M+M)%M);
	return 0;
}

m不互质的情况:扩展中国剩余定理
洛谷P4777

#include<cstdio>
typedef long long ll;
const int maxn=1e5+10;
ll qmul(ll a,ll b,ll mod){
    ll ans=0;
    while(b>0){
        if(b&1) ans=(ans+a)%mod;
        a=(a+a)%mod;
        b>>=1;
    }
    return ans;
}
ll exgcd(ll a,ll b,ll &x,ll &y)
{
    if(b==0){x=1;y=0;return a;}
    ll gcd=exgcd(b,a%b,x,y);
    ll tp=x;
    x=y; y=tp-a/b*y;
    return gcd;
}
int main(){
	ll a[maxn],b[maxn];
	ll n;
	scanf("%lld",&n);
	for(int i=0;i<n;i++)
		scanf("%lld%lld",&b[i],&a[i]);
	ll M=b[0],ans=a[0];//第一组特判
	for(int i=1;i<n;i++){
		ll x,y,c=(a[i]-ans%b[i]+b[i])%b[i];
		ll gcd=exgcd(M,b[i],x,y);
		if(c%gcd!=0)	return -1;//无解情况
		x=qmul(x,c/gcd,b[i]/gcd);
		ans+=x*M;
		M*=b[i]/gcd; 
		ans=(ans%M+M)%M;
	}
	
	printf("%lld",ans); 
	return 0;
}
发布了36 篇原创文章 · 获赞 11 · 访问量 663

猜你喜欢

转载自blog.csdn.net/weixin_43822647/article/details/102668419