zoukankan      html  css  js  c++  java
  • 中国剩余定理与扩展中国剩余定理

    中国剩余定理与扩展中国剩余定理

    概述

    中国剩余定理是同余中常用的辅助手段,常用来合并多个同余方程的解(如MTT)。其技术难度不高,代码也很短,可以在NOIP中出现。

    中国剩余定理CRT

    形式

    给定 (n) 组非负整数 (m_i, a_i) ,求解关于 (x) 的方程组的最小非负整数解。

    [egin{cases} x equiv a_1 ({ m mod} m_1) \ xequiv a_2 ({ m mod} m_2) \ ... \ x equiv a_n ({ m mod} m_n)end{cases} ]

    其中(m_i)两两互质。

    解法

    我们贪心构造和式使得每一项在模意义下不影响其他项,并且符合当前的方程,
    (M =prod^{n}_{i=1}m_i,M_i=frac{M}{m_i}),可以构造解

    [x=sum^{n}_{i=1}M_i(a_iM_i^{-1} mod m_i) ]

    可以证明解在模M 意义下唯一。

    模板题:P3868 [TJOI2009]猜数字
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int INF=1e9+7,MAXN=11;
    inline LL mult(LL a,LL b,LL mod){
    	LL ret=0;
    	while(b>0){
    		if(b&1)
    			ret=(ret+a)%mod;
    		a=(a+a)%mod;
    		b>>=1;
    	}
    	return ret;
    }
    void exgcd(LL a,LL b,LL &x,LL &y){
    	if(!b){
    		x=1;
    		y=0;
    		return;
    	}
    	exgcd(b,a%b,y,x);
    	y-=a/b*x;
    }
    inline LL inv(LL x,LL p){
    	LL a,b;
    	exgcd(x,p,a,b);
    	return (a%p+p)%p;
    }
    int N;
    LL a[MAXN],b[MAXN],M,lcm=1,ans;
    int main(){
    	scanf("%d",&N);
    	for(int i=1;i<=N;i++)
    		scanf("%lld",a+i);
    	for(int i=1;i<=N;i++){
    		scanf("%lld",b+i);
    		lcm*=b[i];
    		a[i]=(a[i]%b[i]+b[i])%b[i];
    	}
    	for(int i=1;i<=N;i++){
    		LL Mi=lcm/b[i],t=inv(Mi,b[i]);
    		ans=(ans+mult(mult(Mi,t,lcm),a[i],lcm))%lcm;
    	}
    	printf("%lld",(ans+lcm)%lcm);
    	return 0;
    }
    

    扩展中国剩余定理EXCRT

    形式

    给定 (n) 组非负整数 (m_i, a_i) ,求解关于 (x) 的方程组的最小非负整数解。

    [egin{cases} x equiv a_1 ({ m mod} m_1) \ xequiv a_2 ({ m mod} m_2) \ ... \ x equiv a_n ({ m mod} m_n)end{cases} ]

    解法

    扩展中国剩余定理的方法和中国剩余定理关系不大,我们贪心处理前(i-1)项,然后合并当前方程。
    将每个方程拆成若干个方程

    [x=a_i(mod p_{i,j}^{k_{i,j}}) ]

    其中(m_i=prod p_{i,j}^{k_{i,j}})(m_i) 的分解式。对每个质数(p),合并对应的所有方程,从而转化为模数两两互质的情形。若合并过程中出现矛盾,则原方程组无解。

    模板题:P4777 【模板】扩展中国剩余定理(EXCRT)
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int INF=1e9+7,MAXN=1e5+10;
    inline LL mult(LL a,LL b,LL mod){
    	LL ret=0;
    	while(b>0){
    		if(b&1)
    			ret=(ret+a)%mod;
    		a=(a+a)%mod;
    		b>>=1;
    	}
    	return ret;
    }
    LL exgcd(LL a,LL b,LL &x,LL &y){
    	if(!b){
    		x=1;
    		y=0;
    		return a;
    	}
    	LL ret=exgcd(b,a%b,y,x);
    	y-=a/b*x;
    	return ret;
    }
    int N;
    LL a[MAXN],b[MAXN],M,ans,x,y;
    int main(){
    	scanf("%d",&N);
    	for(int i=1;i<=N;i++){
    		scanf("%lld%lld",b+i,a+i);
    		a[i]=(a[i]%b[i]+b[i])%b[i];
    	}
    	M=b[1];
    	ans=a[1];
    	for(int i=2;i<=N;i++){
    		LL rm=(a[i]-ans%b[i]+b[i])%b[i];
    		LL gcd=exgcd(M,b[i],x,y);
    		LL bg=b[i]/gcd; 
    		/*if(rm%gcd):ERROR*/
    		x=mult(x,rm/gcd,bg);
    		ans+=x*M;
    		M*=bg;
    		ans=(ans%M+M)%M;
    	}
    	printf("%lld",ans);
    	return 0;
    }
    
  • 相关阅读:
    Android
    列出控制原理来解决
    【ORACLE】spfile失落的处理
    Cocos2d-x 脚本语言Lua基本语法
    远东转载这说明一些有实力的话人工智能协会的思维和潜意识之间移动的一篇文章
    日志框架的实时变化,即日起,思维详细框架(4)
    [Python] Scatter Plot for daily return
    [Python] Use a Python Generator to Crawl the Star Wars API
    [Poi] Setup PostCSS and Tailwind with Poi
    [Poi] Build and Analyze Your JavaScript Bundles with Poi
  • 原文地址:https://www.cnblogs.com/guoshaoyang/p/11296138.html
Copyright © 2011-2022 走看看