zoukankan      html  css  js  c++  java
  • [中国剩余定理]【学习笔记】

    求解同余方程请看 http://www.cnblogs.com/candy99/p/5765986.html
    [2017-02-14 19:05]
    [2017-03-23 update]:看组合数学的时候发现了一个证明,记一下;改成了markdown


    Chinese Remainder Theorem 中国剩余定理

    定理

    考虑两个方程的情况

    [x equiv a pmod m \ x equiv b pmod n ]

    对于n个整数(a, m+a, 2m+a , ... , (n-1)m+a), 用反证法可以证明,每个数(mod n)都有都有不同的余数
    根据鸽巢原理(b)必定作为余数出现了且只出现一次,因此这(n)个数中存在唯一的(x)满足上式


    应用

    求解同余方程组

    [xequiv a_1pmod {m_1}\ xequiv a_2pmod {m_2} \ xequiv a_3pmod {m_3}\ ...\xequiv a_npmod {m_n} ]

    其中 $ (m_i,m_j)=1, 1le i < jle n $


    **直接构造解:**

    (M =prod_{i=1}^{m} m_i)

    首先明确(x mod M)有唯一解

    $ M=m_1 * m_2 * m_3 * ... * m_k $

    $ x=(sumlimits_{i=1}^k a_i* {Mover m_i} *inv({Mover m_i},m_i))mod M $

    证明:
    (x mod m_i)时 第(i)个式子因为有乘逆元所以结果是ai*1,其他式子的(M)可以整除(m_i)所以都是(0),方程组成立


    代码

    
    ll m[N],a[N],M=1;
    void exgcd(ll a,ll b,ll &d,ll &x,ll &y){
    	if(b==0) d=a,x=1,y=0;
    	else exgcd(b,a%b,d,y,x),y-=(a/b)*x;
    }
    ll Inv(ll a,ll p){
    	ll d,x,y;
    	exgcd(a,p,d,x,y);
    	return d==1?(x+p)%p:-1;
    }
    ll CRT(int n,ll *a,ll *m){
    	ll x=0;
    	for(int i=1;i<=n;i++){
    		ll w=M/m[i];
    		x=(x+a[i]*w%M*Inv(w,m[i]))%M;
    	}
    	return x;
    }
    
    
    

    合并同余方程

    如果不满足m两两互质,我们采用合并同余方程的方法将方程两两合并

    两个方程可以写成$ x=m_1 * t_1+a_1=m_2 * t_2+a_2 $

    变形 $ m_1 * t_1-m_2 * t_2=a_2-a_1 $

    线性不定方程的形式

    $ d=gcd(m_1,m_2) $ 有解满足 $d| (a_2-a_1) $

    (exgcd)后乘(frac{a2-a1}{d})解出(t_1)当前是(mod frac{m_2}{d})意义下

    代入(x = m_1*t_1+a_1)中,就变成(mod frac{m_1*m_2}{d})意义下了

    所以合并后方程为 $xequiv m_1*t_1 + a_1pmod {lcm(m_1,m_2)} $

    注意 (t_1)理论上是绝对值最小解,但也许是因为乘了(frac{a2-a1}{d})之后吧求最小的时候不能简单的if(t1<0) t1+=m2啦,需要模一下再变正

    代码

    
    void exgcd(ll a,ll b,ll &d,ll &x,ll &y){
    	if(b==0) d=a,x=1,y=0;
    	else exgcd(b,a%b,d,y,x),y-=(a/b)*x;
    }
    int main(){
    	freopen("in","r",stdin);
    	while(scanf("%lld",&n)!=EOF){
    		int flag=0;
    		m1=read();a1=read();n--;
    		while(n--){
    			m2=read();a2=read();
    			if(flag) continue;
    			ll d,t1,t2;
    			exgcd(m1,m2,d,t1,t2);
    			if((a2-a1)%d){flag=1;continue;}
    			t1*=(a2-a1)/d;
    			m2/=d;
    			t1=(t1%m2+m2)%m2;
    			a1=a1+m1*t1;
    			m1*=m2;
    		}
    		if(flag) puts("-1");
    		else printf("%lld
    ",a1);
    	}
    }
    
    
    
  • 相关阅读:
    PHPStorm--美化
    Laravel5.1 模型--关联关系(复杂)
    HTML5 getUserMedia/AudioContext 打造音谱图形化
    如何在终端实时展现当前运行的git分支
    关于ionic的跨域问题
    ionic插件安装与卸载
    虚拟机调试ionic项目
    ionic双击退出键退出APP
    npm install 镜像
    对Date的扩展,将 Date 转化为指定格式的String
  • 原文地址:https://www.cnblogs.com/candy99/p/6603455.html
Copyright © 2011-2022 走看看