题目传送门:http://poj.org/problem?id=1006
题目大意:给出四个数a,b,c,d,要你求一个大于d的最小数字ans使得 ans≡a(mod23),ans≡b(mod28),ans≡c(mod33) a n s ≡ a ( mod 23 ) , a n s ≡ b ( mod 28 ) , a n s ≡ c ( mod 33 ) 。
题目分析:很早就听说这是道CRT的经典例题。真正看了之后感觉暴力也能过,结果写了一发真能过……时间复杂度同样是 O(1) O ( 1 ) ,只不过有个21252的常数而已QAQ。
然而CRT可以做得更好。直接扔进CRT的式子,跑个Exgcd算一下,就可以知道答案是将a乘以5544加b乘以14421加c乘以1288模21252。注意答案要大于d。
CODE(暴力):
#include<iostream>
#include<string>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<stdio.h>
#include<algorithm>
using namespace std;
int t=0;
int a,b,c,d;
int main()
{
freopen("1006.in","r",stdin);
freopen("1006.out","w",stdout);
scanf("%d%d%d%d",&a,&b,&c,&d);
while (a!=-1)
{
a%=23;
b%=28;
c%=33;
t++;
int ans=d+1;
while ( ans%23!=a || ans%28!=b || ans%33!=c ) ans++;
printf("Case %d: the next triple peak occurs in %d days.\n",t,ans-d);
scanf("%d%d%d%d",&a,&b,&c,&d);
}
return 0;
}
CODE(CRT):
//#include<iostream>
//#include<string>
//#include<cstring>
//#include<cmath>
#include<cstdio>
//#include<cstdlib>
//#include<stdio.h>
//#include<algorithm>
using namespace std;
int t=0;
int a,b,c,d;
int ans;
//int X,Y;
//int p,q,r;
/*void Exgcd(int u,int v)
{
if (!v) X=1,Y=0;
else
{
Exgcd(v,u%v);
int x=X;
int y=Y;
X=y;
Y=x-u/v*y;
}
}*/
int main()
{
freopen("1006.in","r",stdin);
freopen("1006.out","w",stdout);
/*Exgcd(23,28*33%23);
while (Y<0) Y+=23;
p=28*33*Y;
Exgcd(28,23*33%28);
while (Y<0) Y+=28;
q=23*33*Y;
Exgcd(33,23*28%33);
while (Y<0) Y+=33;
r=23*28*Y;*/
scanf("%d%d%d%d",&a,&b,&c,&d);
while (a!=-1)
{
//a%=23;
//b%=28;
//c%=33;
++t;
ans=(a*5544+b*14421+c*1288)%21252;
if (ans<=d) ans+=21252;
printf("Case %d: the next triple peak occurs in %d days.\n",t,ans-d);
scanf("%d%d%d%d",&a,&b,&c,&d);
}
return 0;
}