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 }
posted @ 2012-10-01 20:40  Naix_x  阅读(215)  评论(2编辑  收藏  举报