中国剩余定理

来源:互联网 发布:月光砖厂淘宝店 编辑:程序博客网 时间:2024/06/07 00:52

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

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

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

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 longvoid 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;} 



0 0
原创粉丝点击