其他分享
首页 > 其他分享> > 扩展中国剩余定理(简介)

扩展中国剩余定理(简介)

作者:互联网

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

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

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

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

下面放代码

#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\n",crt());
	
	return 0;
}

标签:剩余,include,简介,定理,ret,ans,线性,同余式,ll
来源: https://www.cnblogs.com/jd1412/p/13359831.html