poj2891 中国剩余定理

来源:互联网 发布:java导出压缩包 编辑:程序博客网 时间:2024/05/29 14:50

对于同余方程组:

      x=a1 (mod m1);    (1)

      x=a2 (mod m2);    (2)

      方程组有一个小于m(m1,m2的最小公倍数)的非负整数解的充分必要条件是(a1-a2)%(m1,m2)==0 ,利用扩展欧几里德算法。

      两式联立:a1+m1*y=a2+m2*z。

      则:a1-a2=m2*z-m1*y; 这样就可以了解出z和y,则:x=a2+m2*z; 

      现在我们将其推广到一般情形:(设m1,m2,···,mk两两互素)

      x=a1(mod m1);

     x=a2(mod m2);

      ···

      x=ak(mod mk);其在M=m1*m2*···*mk;中有唯一整数解。

      记Mi=M/mi;因为(Mi,mi)=1,故有两整数pi,qi满足Mi*pi+mi*qi=1,如果记ei=Mi*pi;那么:

ei=0 (mod mj),j!=i;

        ei=1(mod mj),j=i;

      很明显,e1*a1+e2*a2+···+ek*ak就是方程的一个解,加减M倍后就可以得到最小非负整数解了。

   这种情况下 :


   a=B[1](mod W[1])  

   a=B[2](mod W[2])  

   ........  

   a=B[n](mod W[n])  

   W[i]与W[j] 互质。

   代码为:

__int64 extend_euclid(__int64 a,__int64 b,__int64 &x,__int64 &y){if(b==0){  x=1;  y=0;  return a;}__int64 gcd=extend_euclid(b,a%b,x,y);__int64 temp=x;x=y;y=temp-(a/b)*y;return gcd;}int China(int B[],int W[],int k)      {             int i;          int d,x,y,a=0,m,n=1;          for(i=0;i<k;i++)          n*=W[i];          for(i=0;i<k;i++)          {          m=n/W[i];             d=ext_euclid(W[i],m,x,y);             a=(a+y*m*B[i])%n;          }          if(a>0)    return a;          else    return(a+n);      }

 

 如果m1,m2,···,mk不互素,那只能两个两个求了。

      x=a1 (mod m1); 

      x=a2 (mod m2);  

      解完后,a=x; m=m1和m2的最小公倍数。即可。

分析:

这道题 ai与aj不是互质的,所以只能两个两个的算:

    x= b1 (mod a1)

    x= b2 (mod a2)

  x= b1 + a1*x = b2 +a2*y


code:

#include <iostream>#include <stdio.h>#include <stdlib.h>#include <string.h>using namespace std;__int64 x,y;__int64 extended_euclid(int s,int t)   //拓展欧拉函数{ __int64 i,temp; if(t==0) {  x=1;  y=0;  return s; } else {  i=extended_euclid(t,s%t);  temp=x;  x=y;  y=temp-(s/t*y);  return i; }}int main(){ __int64 a1,a2,b1,b2,t,c,n,m,i,j; while(scanf("%I64d",&t)!=EOF) {  scanf("%I64d%I64d",&a1,&b1);  int ok=0;  for(i=0;i<t-1;i++)  {   scanf("%I64d%I64d",&a2,&b2);   if(ok) continue;   int e=extended_euclid(a1,a2);   c=b2-b1;   if(c%e)   {    ok=1;    continue;   }   int q=a2/e;   x=(x*c/e%q+q)%q;      //求最小的解。。   b1=a1*x+b1;           // b=x;   a1=a1*a2/e;           // a为a1和a2的最小公倍数。  }  if(ok) printf("-1\n");  else printf("%lld\n",b1); } return 0;}


原创粉丝点击