生理週期(中國剩餘定理)

生理週期


Time Limit:1 Ms| Memory Limit:128 MB
Difficulty:1

Description

人生來就有三個生理週期,分別爲體力、感情和智力週期,它們的週期長度爲23天、28天和33天。每一個週期中有一天是高峯。在高峯這天,人會在相應的方面表現出色。例如,智力週期的高峯,人會思維敏捷,精力容易高度集中。因爲三個週期的周長不同,所以通常三個週期的高峯不會落在同一天。對於每個人,我們想知道何時三個高峯落在同一天。對於每個週期,我們會給出從當前年份的第一天開始,到出現高峯的天數(不一定是第一次高峯出現的時間)。你的任務是給定一個從當年第一天開始數的天數,輸出從給定時間開始(不包括給定時間)下一次三個高峯落在同一天的時間(距給定時間的天數)。例如:給定時間爲10,下次出現三個高峯同天的時間是12,則輸出2(注意這裏不是3)。

Input

輸入四個整數:p, e, i和d。 p, e, i分別表示體力、情感和智力高峯出現的時間(時間從當年的第一天開始計算)。d 是給定的時間,可能小於p, e, 或 i。 所有給定時間是非負的並且小於365, 所求的時間小於21252。 

當p = e = i = d = -1時,輸入數據結束。

Output

從給定時間起,下一次三個高峯同天的時間(距離給定時間的天數)。 

採用以下格式: 
Case 1: the next triple peak occurs in 1234 days. 

注意:即使結果是1天,也使用複數形式“days”。

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.

Hint

用 scanf 接受數據

資料轉自:http://www.cnblogs.com/walker01/archive/2010/01/23/1654880.html

我們將“孫子問題”拆分成幾個簡單的小問題,從零開始,試圖揣測古人是如何推導出這個解法的。
     首先,我們假設n1是滿足除以3餘2的一個數,比如2,5,8等等,也就是滿足3*k+2(k>=0)的一個任意數。同樣,我們假設n2是滿足除以5餘3的一個數,n3是滿足除以7餘2的一個數。
     有了前面的假設,我們先從n1這個角度出發,已知n1滿足除以3餘2,能不能使得 n1+n2 的和仍然滿足除以3餘2?進而使得n1+n2+n3的和仍然滿足除以3餘2?
     這就牽涉到一個最基本數學定理,如果有a%b=c,則有(a+kb)%b=c(k爲非零整數),換句話說,如果一個除法運算的餘數爲c,那麼被除數與k倍的除數相加(或相減)的和(差)再與除數相除,餘數不變。這個是很好證明的。
     以此定理爲依據,如果n2是3的倍數,n1+n2就依然滿足除以3餘2。同理,如果n3也是3的倍數,那麼n1+n2+n3的和就滿足除以3餘2。這是從n1的角度考慮的,再從n2,n3的角度出發,我們可推導出以下三點:
爲使n1+n2+n3的和滿足除以3餘2,n2和n3必須是3的倍數。
爲使n1+n2+n3的和滿足除以5餘3,n1和n3必須是5的倍數。
爲使n1+n2+n3的和滿足除以7餘2,n1和n2必須是7的倍數。
    因此,爲使n1+n2+n3的和作爲“孫子問題”的一個最終解,需滿足:
n1除以3餘2,且是5和7的公倍數。
n2除以5餘3,且是3和7的公倍數。
n3除以7餘2,且是3和5的公倍數。
    所以,孫子問題解法的本質是從5和7的公倍數中找一個除以3餘2的數n1,從3和7的公倍數中找一個除以5餘3的數n2,從3和5的公倍數中找一個除以7餘2的數n3,再將三個數相加得到解。在求n1,n2,n3時又用了一個小技巧,以n1爲例,並非從5和7的公倍數中直接找一個除以3餘2的數,而是先找一個除以3餘1的數,再乘以2。
    這裏又有一個數學公式,如果a%b=c,那麼(a*k)%b=a%b+a%b+…+a%b=c+c+…+c=kc(k>0),也就是說,如果一個除法的餘數爲c,那麼被除數的k倍與除數相除的餘數爲kc。展開式中已證明。
    最後,我們還要清楚一點,n1+n2+n3只是問題的一個解,並不是最小的解。如何得到最小解?我們只需要從中最大限
度的減掉掉3,5,7的公倍數105即可。道理就是前面講過的定理“如果a%b=c,則有(a-kb)%b=c”。所以(n1+n2+n3)%105就是最終的最小解。
總結
   經過分析發現,中國剩餘定理的孫子解法並沒有什麼高深的技巧,就是以下兩個基本數學定理的靈活運用:
如果 a%b=c , 則有 (a+kb)%b=c (k爲非零整數)。
如果 a%b=c,那麼 (a*k)%b=kc (k爲大於零的整數)。

#include<stdio.h>
int main(){
//	freopen("in.txt", "r", stdin);
   // freopen("out.txt", "w", stdout);
	int e, p, i, d;
	int j, ans, count = 0; 
	int a, b, c;
	int a1 = 28 * 33, a2 = 23 * 33, a3 = 23 * 28;//a1 = lcm(28, 33)//公倍數
	for(j = 0; j < 365; j++){
		if((j * a1) % 23 == 1){
			a = j * a1;
			break;	
        }
	}
	for(j = 0; j < 365; j++){
		if((j * a2) % 28 == 1){
			b = j * a2; 
			break;
		}
	}
	for(j = 0; j < 365; j++){
		if((j * a3) % 33 == 1){
			c = j * a3;
			break;
		}
	}
	while(1){
		
		ans = 0;
		count++;
		scanf("%d%d%d%d", &e, &p, &i, &d);
		
        if(e == -1 && p == -1 && i == -1 && d == -1)
			break;	
		else if(e == 0 && p == 0 && i == 0){//特殊情況
		    ans = 21252;			
		}			
		else{			
			ans = ((a * e + b * p + c * i) );
		}		
		ans = ans % 21252 - d;
		if(ans <= 0){//如果ans-d是小於0的數, 就要再加上一個週期
		    ans += 21252;
		}
		printf("Case %d: the next triple peak occurs in %d days.\n", count, ans);
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章