zoukankan      html  css  js  c++  java
  • 扩展中国剩余定理(简介)

    扩展中国剩余定理(普通线性同余不等式组)板子题

    对于中国剩余定理来说,每一个线性同余式所要求的的模数均为素数,这就在一定程度上限制了中国剩余定理的使用(但不能否认这是一个很有用而且很好用的算法)

    因此,我们需要找到一种对于模数不互质的线性同余式组的更普遍的求解算法

    扩展中国剩余定理构造求解

    • 对于一个线性同余方程组:

    • 我们首先假定一个数 (x) 为线性同余式组的前 (k-1) 个解,此时有 (M = lcm ( m1,m2,……,m_i ))

      则对于前 (k-1) 个线性同余式的通解为:(x + i imes M ( i in Z))

      那么对于第 (k) 个线性同余式,我们只需要找到一个数 (t) ,满足 (x + t imes M equiv a_k (mod m_k )) 即可

      整理一下,即可得到:(t imes M equiv a_k - x ( mod m_k )),对于整理得到的式子,我们就可以用扩展欧几里得算法求得 (t) 的值,再对答案进行累加即可

      所以,依次类推,对含有 (k) 个线性同余式的同余式组,只需使用 (k-1) 次扩展欧几里得算法即可求得答案

    下面放代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<math.h>
    #include<algorithm>
    #define ll long long
    using namespace std;
    
    const ll maxn=1e6+10;
    ll ai[maxn],bi[maxn];
    ll n;
    ll M,ans,bx;
    
    inline ll exgcd(ll a,ll b,ll &x,ll &y) //扩展欧几里得
    {
    	if(b==0)
    	{
    		x=1,y=0;
    		return a;
    	}
    	ll d=exgcd(b,a%b,x,y);
    	ll z=x;
    	x=y;
    	y=z-(a/b)*y;
    	return d;
    }
    
    inline ll multi(ll a,ll b,ll p)	 //龟速乘,避免乘法溢出 
    {
    	ll ret=0;
    	
    	while(b)
    	{
    		if(b&1)
    		{
    			ret=(ret+a)%p;
    		}
    		a=(a+a)%p;
    		b>>=1;
    	}
    	return ret;
    }
    
    inline ll crt()     			// excrt 求解 
    {
    	ll x,y,k,t;
    	
    	ll M=bi[1],ans=ai[1];		//初始时对 ans 和  M 进行预处理,将第一个同余式中的模数与余数赋给 M 和 ans ,作为第一组解 
    	
    	for(int i=2;i<=n;i++) 		//注意要进行 n-1 次循环 
    	{
    		ll a=M;
    		ll b=bi[i];
    		ll c=(ai[i]-ans%b+b)%b;  
    		ll g=exgcd(a,b,x,y);	//在进行扩展欧几里得算法时,求解的是 M * x + b[i] * y = gcd( M , b[i] ) 中 x 和 y 的值 , 并可顺便将 gcd( M , b[i] ) 求得 
    		if(c%g!=0) return -1; 	//目标解不能被 gcd ( M , b[i] ) 整除 , 说明该同余式无解 
    		bx=b/g;
    		x=multi(x,c/g,bx);
    		ans+=x*M;		//累加答案 
    		M*=bx;			//求 b[1] 到 b[i] 的 lcm
    		ans=(ans%M+M)%M;
    	}
    	
    	return (ans%M+M)%M;
    }
    
    int main(void)
    {
    	scanf("%lld",&n);
    	
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%lld%lld",&bi[i],&ai[i]);
    	}
    	
    	printf("%lld
    ",crt());
    	
    	return 0;
    }
    
  • 相关阅读:
    linux 部署项目命令
    List remove方法小坑
    centos7 安装mongoDB
    windows git 清除已保存的密码
    windows平台安装配置Gitblit
    oracle
    Mac 配置多jdk 随意切换
    idea远程调试jar包
    centos7 安装elasticsearch
    正则校验
  • 原文地址:https://www.cnblogs.com/jd1412/p/13359831.html
Copyright © 2011-2022 走看看