题意:有3个循环周期,周期天数分别为23、28、33。对于某一年,已知某年这3个周期的某一峰值分别是当年的第p、e、i天,问从第d天开始到最近一个满足3个周期都达到峰值的日期还有多少天。
数据比较小,直接打表可过:
# include <stdio.h> int tab[40][40][40]; int cal(int num) { if (num <= 0) return num + 21252 ; return num ; } int main () { int p,e,i,d,T, nCase ; for (i = 0 ; i < 21252 ; i++) tab[i%23][i%28][i%33] = i ; scanf ("%d", &T) ; while (T--) { nCase = 1 ; while (1) { scanf ("%d%d%d%d", &p, &e, &i, &d) ; if (p==-1&&e==-1&&i==-1&&d==-1) break ; printf ("Case %d: " "the next triple peak occurs in %d days.\n", nCase++, cal(tab[p%23][e%28][i%33]-d)) ; } if (T) putchar ('\n') ; } return 0 ; }
中国剩余定理效率更高:0MS
#include <iostream> using namespace std; int exgcd(int a,int b,int &x,int &y) { if(a==0) { x=0; y=1; return b; } int g = exgcd(b%a,a,x,y); int tem = y; y=x; x=tem-(b/a)*y; return g; } int inv(int a,int n)//求逆元 { int x,y; exgcd(a,n,x,y); return (x%n+n)%n; } int main() { int N,P,E,I,D,ans; const int m1=23,m2=28,m3=33,M1=28*33,M2=23*33,M3=23*28,m=23*28*33; const int M11 = inv(M1,m1),M22 = inv(M2,m2),M33 = inv(M3,m3);//求mi的逆元 scanf("%d",&N); while(scanf("%d%d%d%d",&P,&E,&I,&D)!=EOF) { if(P==-1&&E==-1&&I==-1&&D==-1)break; //a[i]*(mi*mi(逆)mod ni)因为在求逆元的时候已经mod ni了 //(mi*mi(逆)mod ni)是ci ans = (P*M1*M11 + E*M2*M22 + I*M3*M33)%m; ans -= D; if(ans<=0) ans+=m; printf("Case %d: the next triple peak occurs in %d days.\n",N++,ans); //cout<<"Case "<<N++<<": the next triple peak occurs in "<<i<<" days.\n"; } return 0; }