POJ 1006/ ZOJ 1160: Biorhythms - 中国剩余定理

题意:p e i分别代表的是三个高峰出现的时间(该年的第几天)d是给出的该年的第几天,让你从这一天开始求到它下一次三个同时高峰所经历的天数



(一)一般解法

解题思路:先确定一天的高峰期,然后每次循环都加23(确保那天是p的高峰期),再去判断是否e,i的高峰期

易错:循环开始前的d++必须的,因为是算下一次三个同高峰   (0 0 0 0可知)

(1) POJ

//Boirhythm
#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
int p,e,i,d;
int date,cas=0;
while(scanf("%d%d%d%d",&p,&e,&i,&d))
{
if(p==-1)
break;
date=d;
d++;
while((d-p)%23!=0) d++;
while((d-e)%28!=0||(d-i)%33!=0) d+=23;
printf("Case %d: the next triple peak occurs in %d days.\n",++cas,d-date);
}
return 0;
}


(2) ZOJ

//Boirhythm
#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
int t,p,e,i,d,date;
scanf("%d",&t);
while(t--)
{
int cas=0;
while(~scanf("%d%d%d%d",&p,&e,&i,&d))
{
if(p==-1)
break;
date=d;
d++;
while((d-p)%23!=0) d++;
while((d-e)%28!=0||(d-i)%33!=0) d+=23;
printf("Case %d: the next triple peak occurs in %d days.\n",++cas,d-date);
}
if(t) puts("");
}
return 0;
}





(二)另法:中国剩余定理http://baike.baidu.com/view/157384.htm?subLemmaId=157384&fromenter=%D6%D0%B9%FA%CA%A3%D3%E0%B6%A8%C0%ED(百科解释)

以下为引用:

在中国古代著名数学著作《孙子算经》中,有一道题目叫做“物不知数”,原文如下:

有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二。问物几何?

即,一个整数除以三余二,除以五余三,除以七余二,求这个整数。


中国数学家秦九韶1247年做出了完整的解答,口诀如下

三人同行七十希,五树梅花廿一支,七子团圆正半月,除百零五使得知

这个解法实际上是,首先利用秦九韶发明的大衍求一术求出5和7的最小公倍数35的倍数中除以3余数为1的最小一个70(这个称为35相对于3的数论倒数),3和7的最小公倍数21相对于5的数论倒数21,3和5的最小公倍数15相对于7的数论倒数15。然后

70 \times 2 + 21 \times 3 + 15 \times 2 = 233

233便是可能的解之一。它加减3、5、7的最小公倍数105的若干倍仍然是解,因此最小的解为233除以105的余数23。

附注:这个解法并非最简,因为实际上35就符合除3余2的特性,所以最小解是:

 35 \times 1 + 21 \times 3 + 15 \times 2- 3 \times 5  \times 7 = 128 - 105 = 23 最小解加上105的正整数倍都是解。


例1:一个数被3除余1,被4除余2,被5除余4,这个数最小是几?

题中3、4、5三个数两两互质。则〔4,5〕=20;〔3,5〕=15;〔3,4〕=12;〔3,4,5〕=60。为了使20被3除余1,用20×2=40;使15被4除余1,用15×3=45;使12被5除余1,用12×3=36。然后,40×1+45×2+36×4=274,因为,274>60,所以,274-60×4=34,就是所求的数。

   例2:一个数被3除余2,被7除余4,被8除余5,这个数最小是几?

题中3、7、8三个数两两互质。则〔7,8〕=56;〔3,8〕=24;〔3,7〕=21;〔3,7,8〕=168。为了使56被3除余1,用56×2=112;使24被7除余1,用24×5=120。使21被8除余1,用21×5=105;然后,112×2+120×4+105×5=1229因为,1229>168,所以,1229-168×7=53【1229%168】,,就是所求的数。


(1)POJ 

//Biorhythm
#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
int p,e,i,d,n;
int num=1;
while(scanf("%d%d%d%d",&p,&e,&i,&d))
{
if(p!=-1)
{
n=(5544*p+14421*e+1288*i-d)%21252;
if(n<=0) n+=21252;
printf("Case %d: the next triple peak occurs in %d days.\n",num++,n);
}
else break;
}
}




(2)ZOJ            ZOJ最爱搞神马古怪的格式输入输出了~~!

//Biorhythm
#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
int t,p,e,i,d,n;
scanf("%d",&t);
while(t--)
{
int num=1;
while(~scanf("%d%d%d%d",&p,&e,&i,&d))
{
if(p==-1) break;
else
{
n=(5544*p+14421*e+1288*i-d)%21252;
if(n<=0) n+=21252;
printf("Case %d: the next triple peak occurs in %d days.\n",num++,n);
}
}
if(t) puts("");
}
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值