POJ 1006 Biorhythms(中国剩余定理)

题目链接

虽然不是很理解,看着模版和讲解对这个题改编了一下,就过了。顺便整理一下中国剩余定理当作模版,在网上居然搜到海大wangs的博客了,第一眼居然没看出来,orz大神。。。以下这段话从他博客上复制的。至于原理百度百科吧。。。

设m1,m2,...,mk是两两互素的正整数,对于任意的正整数a1,a2,a3,..,ak 同余方程组:

x≡a1 (mod m1)
x≡a2 (mod m2)
...
x≡ak (mod mk)
必有解, 且解可写为
x≡M1N1a1+MkNkak+....MkNkak (mod m)
其中 m=m1m2m3....mk
Mi=m/mi,(1<=i<=k)
Nj满足MjNj≡1(mod mj),1<=j<=k
即:
Ni,Mi是对模mi的互为逆元。

 

中国剩余定理代码实现,就是用扩展欧几里得求出n/mi模mi的逆元。就是ext_eulid(n/mi,1)后,求得的x就是逆元。(n代表m数组所有数的乘积)

ans = sum(逆元*n/mi *ai) % n;sum代表求和

这个题代码:

 1 #include <cstdio>

 2 #include <iostream>

 3 #include <cstring>

 4 #include <cmath>

 5 using namespace std;

 6 #define N 100000

 7 int x,y;

 8 int ext_eulid(int a,int b)

 9 {

10     int t,d;

11     if(b == 0)

12     {

13         x = 1;

14         y = 0;

15         return a;

16     }

17     d = ext_eulid(b,a%b);

18     t = x;

19     x = y;

20     y = t - (a/b)*y;

21     return d;

22 }

23 int main()

24 {

25     int p,e,i,d,num = 0,ans,n;

26     while(scanf("%d%d%d%d",&p,&e,&i,&d)!=EOF)

27     {

28         if(p==-1&&e==-1&&i==-1&&d==-1) break;

29         num ++;

30         ans = 0;

31         printf("Case %d:",num);

32         n = 23*28*33;

33         n/23*ext_eulid(n/23,23);

34         x = (x+23)%23;

35         ans = (ans + p*x*n/23)%n;

36         ext_eulid(n/28,28);

37         x = (x+28)%28;

38         ans = (ans + e*x*n/28)%n;

39         ext_eulid(n/33,33);

40         x = (x+33)%33;

41         ans = (ans + i*x*n/33)%n;

42         if(ans - d > 0)

43         printf(" the next triple peak occurs in %d days.\n",ans-d);

44         else

45         printf(" the next triple peak occurs in %d days.\n",ans+21252-d);

46     }

47     return 0;

48 }

中国剩余定理模版

 1 ll x,y;

 2 ll ext_eulid(ll a,ll b)

 3 {

 4     int t,d;

 5     if(b == 0)

 6     {

 7         x = 1;

 8         y = 0;

 9         return a;

10     }

11     d = ext_eulid(b,a%b);

12     t = x;

13     x = y;

14     y = t - (a/b)*y;

15     return d;

16 }

17 ll CRT(ll *p,ll *o,int num)//p数组代表余数,o数组代表互质的数

18 {

19     int i;

20     ll ans = 0,n = 1;

21     for(i = 1;i <= num;i ++)

22     {

23         n *= o[i];

24     }

25     for(i = 1;i <= num;i ++)

26     {

27         ext_eulid(n/o[i],o[i]);

28         x = (x+o[i])%o[i];

29         ans = (ans + n/o[i]*p[i]*x) % n;

30     }

31     return ans;

32 }

你可能感兴趣的:(poj)