中国剩余定理

中国剩余定理:求解一次同余式组

对于特殊的中国剩余定理:即要求m[1],m[2].....m[n]两两互素

 1 int fun(int a[], int m[], int n){
 2     int M = 1;
 3     int i;
 4     for(i=0; i<n; i++){
 5         M *= m[i];
 6     }
 7     int X = 0;
 8     for(i=0; i<n; i++){
 9         int x, y;
10         int Mi = M/m[i];
11         exgcd(Mi, m[i], x, y);
12         X = (X + a[i]*Mi*x) % M;
13     }
14     if(X<0)
15         X += M;
16     return X;
17 }

 

例:poj-1006 http://poj.org/problem?id=1006

题目大意:人自出生起就有体力,情感和智力三个生理周期,分别为23,28和33天。一个周期内有一天为峰值,通常这三个周期的峰值不会是同一天。

现在给出三个日期,分别对应体力、情感、智力出现等值的日期,给定一个从当年第一天开始数的天数,输出从给定时间开始(不包括给定时间)下一次

三个高峰落在同一天的时间(距给定时间的天数)。

附代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 using namespace std;
 7 int m[4] = {23, 28, 33};
 8 int a[4];
 9 void exgcd(int a, int b, int &x, int &y){ //求逆元
10     if(b==0){
11         x = 1;
12         y = 0;
13         return ;
14     }
15     exgcd(b, a%b, x, y);
16     int t = x;
17     x = y;
18     y = t-a/b*y;
19     return;
20 }
21 int fun(int a[], int m[], int n){ //中国剩余定理
22     int M = 1;
23     int i;
24     for(i=0; i<n; i++){
25         M *= m[i];
26     }
27     int X = 0;
28     for(i=0; i<n; i++){
29         int x, y;
30         int Mi = M/m[i];
31         exgcd(Mi, m[i], x, y);
32         X = (X + a[i]*Mi*x) % M;
33     }
34     if(X<0)
35         X += M;
36     return X;
37 }
38 int main(){
39     int i, j, k, d, cas = 1;
40     while(cin>>a[0]>>a[1]>>a[2]>>d){
41         if(a[0]==a[1]&&a[1]==a[2]&&a[2]==d&&d==-1)
42             break;
43         int ans = fun(a,m,3);
44         if(ans<d)
45             ans += 21252;
46         //cout<<ans-d<<endl;
47         printf("Case %d: the next triple peak occurs in %d days.\n",cas++, ans-d);
48     }
49     return 0;
50 }

 

 

对于一般形式的中国剩余定理:

 

posted @ 2016-07-13 11:08  頔頔  阅读(332)  评论(0编辑  收藏  举报