中国剩余定理

看了一个大神的博客:点击打开链接

我认为这个拓展欧几里得差不多还是一个模版的问题,其实真正能在模版之中加入自己东西才是王者,好吧!很明显我们需要先学会模版,首先你需要会拓展欧几里得哦

按照上面的公式我们需要一步一步的去求解。

1、求出M,M=m1*m2*m3*m4*……………..mk;

2、我们需要求出Mi=M/mi;

3、然后利用拓展欧几里得求出Mi^(-1);exgcd(Mi,mi,x1,y),x1就是需要的值。

4、最后就可以求出x的值,对于每一个ai*Mi*xmod(M)相加即可

5、根据实际的情况输出x的值,如果x小于0,需要的x大于0;这是需要变换一下,x+=M;如果本来就需要负值,那就直接输出


<span style="font-size:18px;">#include<cstdio>
 
void exgcd(__int64 a,__int64 b,__int64 &x,__int64&y)
{
	if(b==0)
	{
		y=0;
		x=1;
		return ;
	}
	else
	{
		exgcd(b,a%b,y,x);
		y-=x*(a/b); 
	} 
} 
__int64 CTR(__int64 a[],__int64 m[],__int64 n)
{
	__int64 M=1,i;
	for(i=0;i<n;++i)
		 M*=m[i];
	__int64 ans=0,x,y;
	for(i=0;i<n;++i)
	{
		__int64 Mi=M/m[i]; 
		exgcd(Mi,m[i],x,y); 
		ans=(ans+Mi*x*a[i])%M; 
	}
	//按照情况而定 
	/*if(ans<0)
		return ans+=M;
	*/
	return ans;
} 
int main()
{
	
	return 0;
} </span>


中国剩余定理   ( CRT )  首先我说一下不互质的情况,因为刚刚才学会,
断断续续搞了3天才算真正的明白 
 假设 x=a1(mod n1)  x=a2(mod n2)........一般我们学的都是互质的情况,对于不互质的
 我们采用的方法是每2个方程结合成一个方程,最后变成只有一个方程的情况,输出最小解
 如何进行合并呢!现在就开始介绍
 x=k1*n1+a1   x=k2*n2+a2 合并化简  k1*n1=k2*n2+a2-a1,设c=a2-a1;
 k1*n1+k2*n2=c;这就变成了exgcd 如果c是d=gcd(n1,n2)的整数倍才有解,不然没有解 
 k1*n1=c(mod n2)->k1*n1/d=c/d(mod n2/d)->k1=(c/d)*(pow(n1/d,-1))mod( n2/d);
 k1=(n2/d)*y+ T (T=pow(n1/d,-1))
 代入方程 x=k1*n1+a1 -> x=n1*T+a1(mod(n1*n2/d)) 
 这里的 n1*T+a1等于 当c=d时,k1的值,这时候我们只需要k1*c/d就可以求出 


#define LL long long
void exgcd(LL a,LL b,LL &d,LL &x,LL &y)
{
	if(b==0)
	{
		y=0;
		x=1;
		d=a;
	} 
	else
	{
		exgcd(b,a%b,d,y,x);
		y-=x*(a/b); 
	} 
} 
LL CRT(LL a[],LL n[],LL num)
{
	LL i,c,k1,k2,n1=n[0],n2,a1,a2,x1,t;
	for(i=1;i<num;++i)
	{
		n2=n[i];a2=a[i];
		c=a2-a1;
		exgcd(n1,n2,d,k1,k2);
		if(c%d)
		{
			return 0;//无解 
		} 
		x1=k1*c/d;//n1*k1+n2*k2=d (k1,k2的解是当c=d时的解)
		t=n2/d;
		x1=(x1%t+t)%t;//求出最小解 
		a1+=x1*n1;
		n1=n1/d*n2;//这时候2个方程已经合并成为1个方程与下一个再次进行合并 
	} 
	return a1;
} 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值