Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 102340 | Accepted: 31576 |
Description
Input
Output
Sample Input
0 0 0 0 0 0 0 100 5 20 34 325 4 5 6 7 283 102 23 320 203 301 203 40 -1 -1 -1 -1
Sample Output
Case 1: the next triple peak occurs in 21252 days. Case 2: the next triple peak occurs in 21152 days. Case 3: the next triple peak occurs in 19575 days. Case 4: the next triple peak occurs in 16994 days. Case 5: the next triple peak occurs in 8910 days. Case 6: the next triple peak occurs in 10789 days.
Source
题意:有3个循环周期,周期天数分别为23、28、33。对于某一年,已知某年这3个周期的某一峰值分别是当年的第p、e、i天,
问从第d天开始到最近一个满足3个周期都达到峰值的日期还有多少天。
思路:
赤裸的中国剩余定理 直接套模板即可
#include <iostream> using namespace std; int Extended_Euclid(int a,int b,int &x,int &y) //扩展欧几里得算法 { int d; if(b==0) { x=1;y=0; return a; } d=Extended_Euclid(b,a%b,y,x); y-=a/b*x; return d; } int Chinese_Remainder(int a[],int w[],int len) //中国剩余定理 a[]存放余数 w[]存放两两互质的数 { int i,d,x,y,m,n,ret; ret=0; n=1; for (i=0;i<len;i++) n*=w[i]; for (i=0;i<len;i++) { m=n/w[i]; d=Extended_Euclid(w[i],m,x,y); ret=(ret+y*m*a[i])%n; } return (n+ret%n)%n; } int main() { int n,i,c,d,C=1,ans; int w[15]={23,28,33},a[15]; scanf("%d",&c); while (scanf("%d %d %d %d",&a[0],&a[1],&a[2],&d)!=EOF) { if(a[1]==-1&&a[2]==-1&&a[0]==-1) break; a[0]%=23; a[1]%=28; a[2]%=33; ans=Chinese_Remainder(a,w,3); ans=ans-d; if(ans<=0) ans=ans+21252; printf("Case %d: the next triple peak occurs in %d days.\n", C++,ans); } return 0; }
枚举方法:
#include<iostream> #include<stdio.h> using namespace std; int main() { int n,i,c,d,C=1,ans; int w[15]={23,28,33},a[15]; while (scanf("%d %d %d %d",&a[0],&a[1],&a[2],&d)!=EOF) { if(a[1]==-1&&a[2]==-1&&a[0]==-1) break; a[0]=a[0]%23; a[1]=a[1]%28; a[2]=a[2]%33; for(i=0;i<21252;i++) if((i-a[0])%23==0) break; for(i;i<=21252;i+=23) { if((i-a[0])%23==0&&(i-a[1])%28==0&&(i-a[2])%33==0) { break; } } ans=i-d; if(ans<=0) ans+=21252; printf("Case %d: the next triple peak occurs in %d days.\n", C++,ans); } return 0; }