中国剩余定理及应用

 

中国剩余定理及应用

分类: 数论   569人阅读  评论(0)  收藏  举报

 

题目:POJ1006 Biorhythms

[cpp]  view plain copy
  1. #include <iostream>  
  2.   
  3. int a[4];  
  4. int m[4];  
  5. int M,x,y,gcd;  
  6.   
  7. void Extend_Euclid(int a,int b)  
  8. {  
  9.     if(b==0)  
  10.     {  
  11.         x=1;  
  12.         y=0;  
  13.         return;  
  14.     }  
  15.     Extend_Euclid(b,a%b);  
  16.     int temp=x;  
  17.     x=y;  
  18.     y=temp-(a/b)*y;  
  19. }  
  20.   
  21. int RemindChina(int r)  
  22. {  
  23.     M=1;  
  24.     int Mi,i,ans=0;  
  25.     for(i=1;i<=r;i++)  
  26.         M*=m[i];  
  27.     for(i=1;i<=r;i++)  
  28.     {  
  29.         Mi=M/m[i];  
  30.         Extend_Euclid(Mi,m[i]);  
  31.         ans=(ans+Mi*x*a[i])%M;  
  32.     }  
  33.     if(ans<0)  
  34.         ans+=M;  
  35.     return ans;  
  36. }  
  37.   
  38. int main()  
  39. {  
  40.     int p,e,i,d,t=1;  
  41.     while(std::cin>>p>>e>>i>>d)  
  42.     {  
  43.         if(p==-1&&e==-1&&i==-1&&d==-1)  
  44.             break;  
  45.         a[1]=p;a[2]=e;a[3]=i;  
  46.         m[1]=23;m[2]=28;m[3]=33;  
  47.         int ans=RemindChina(3);  
  48.         if(ans<=d)  
  49.             ans+=21252;  
  50.         std::cout<<"Case "<<t++<<": the next triple peak occurs in "<<ans-d<<" days."<<std::endl;  
  51.     }  
  52.     return 0;  
  53. }  
  54.  

    广义的中国剩余定理

    分类: 数论   115人阅读  评论(0)  收藏  举报

    广义的中国剩余定理

    对于方程x≡a[i] (mod m[i])m[i]m[j]不互素,怎样求x

    中国剩余定理中求同余方程组的模数都是两两互质的,但是这个题目里面可能不是两两互质,所以需要转换一下

    1x=b1(mod a1);

    2x=b2(mod a2);

    a1*x1+b1=x=b2(mod a2)

    所以a1*x1+b1=b2(mod a2)

           a1*x1=(b2-b1)(mod a2)

    形如AX==B(mod p)的同余式可用扩张欧几里德算法求出一个最小的一个X。所以容易求出x1的值,代入1)式,得出x.

    接着这一步很关键的是将该两个方程合并成一个方程:xx=x(mod lcm(a1,a2) );

    主要用了合并的思想

    x≡ r1 mod a1       x ≡ r2 mod a2

    则可以通过等式转换为一个等式x≡r mod a,然后一直合并下去,最终只有一个同余方程式。

     

    题目: Strange Way to Express Integers
     
    [cpp]  view plain copy
    1. #include <iostream>  
    2. #include <cstdio>  
    3. #include <string.h>  
    4.   
    5. using namespace std;  
    6.   
    7. #define LL long long  
    8.   
    9. const int N = 1010;  
    10.   
    11. LL gcd(LL a,LL b)  
    12. {  
    13.     return b? gcd(b,a%b):a;  
    14. }  
    15.   
    16. void extend_Euclid(LL a,LL b,LL &x,LL &y)  
    17. {  
    18.     if(b==0)  
    19.     {  
    20.         x = 1;  
    21.         y = 0;  
    22.         return;  
    23.     }  
    24.     extend_Euclid(b,a%b,x,y);  
    25.     LL temp=x;  
    26.     x=y;  
    27.     y=temp-a/b*y;  
    28. }  
    29.   
    30. LL inv(LL a,LL b)  
    31. {  
    32.     LL d = gcd(a,b);  
    33.     if(d != 1)  
    34.         return -1;  
    35.     LL x,y;  
    36.     extend_Euclid(a,b,x,y);  
    37.     return (x % b + b) % b;  
    38. }  
    39.   
    40. bool merge(LL a1,LL r1,LL a2,LL r2,LL &a3,LL &r3)  
    41. {  
    42.     LL d = gcd(a1,a2);  
    43.     LL c = r2 - r1;  
    44.     if(c % d)  
    45.         return false;  
    46.     c = (c % a2 + a2) % a2;  
    47.     a1 /= d;  
    48.     a2 /= d;  
    49.     c /= d;  
    50.     c *= inv(a1,a2);  
    51.     c %= a2;  
    52.     c *= (a1*d);  
    53.     c += r1;  
    54.     a3 = a1 * a2 * d;  
    55.     r3 = (c % a3 + a3) % a3;  
    56.     return true;  
    57. }  
    58.   
    59. LL China_Remain(LL n,LL a[],LL r[])  
    60. {  
    61.     LL a1 = a[1],r1 = r[1];  
    62.     for(LL i = 2;i <= n;i++)  
    63.     {  
    64.         LL a2,r2,a3,r3;  
    65.         a2 = a[i];  
    66.         r2 = r[i];  
    67.         if(!merge(a1,r1,a2,r2,a3,r3))  
    68.         {  
    69.              return -1;  
    70.         }  
    71.         a1 = a3;  
    72.         r1 = r3;  
    73.     }  
    74.     return (r1%a1+a1)%a1;  
    75. }  
    76.   
    77. int main()  
    78. {  
    79.     LL i, n;  
    80.     LL a[N],r[N];  
    81.     while(~scanf("%I64d",&n))  
    82.     {  
    83.         memset(a,0,sizeof(a));  
    84.         memset(r,0,sizeof(r));  
    85.         for(i = 1;i <= n;++i)  
    86.             scanf("%I64d%I64d",&a[i],&r[i]);  
    87.         LL ans = China_Remain(n,a,r);  
    88.         printf("%I64d\n",ans);  
    89.     }  
    90.     return 0;  
    91. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值