1. 程式人生 > >【POJ 1006】【CRT(中國剩餘定理)模板題】Biorhythms

【POJ 1006】【CRT(中國剩餘定理)模板題】Biorhythms

描述:
Biorhythms
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 130935 Accepted: 41750

Description

Some people believe that there are three cycles in a person's life that start the day he or she is born. These three cycles are the physical, emotional, and intellectual cycles, and they have periods of lengths 23, 28, and 33 days, respectively. There is one peak in each period of a cycle. At the peak of a cycle, a person performs at his or her best in the corresponding field (physical, emotional or mental). For example, if it is the mental curve, thought processes will be sharper and concentration will be easier. 
Since the three cycles have different periods, the peaks of the three cycles generally occur at different times. We would like to determine when a triple peak occurs (the peaks of all three cycles occur in the same day) for any person. For each cycle, you will be given the number of days from the beginning of the current year at which one of its peaks (not necessarily the first) occurs. You will also be given a date expressed as the number of days from the beginning of the current year. You task is to determine the number of days from the given date to the next triple peak. The given date is not counted. For example, if the given date is 10 and the next triple peak occurs on day 12, the answer is 2, not 3. If a triple peak occurs on the given date, you should give the number of days to the next occurrence of a triple peak. 

Input

You will be given a number of cases. The input for each case consists of one line of four integers p, e, i, and d. The values p, e, and i are the number of days from the beginning of the current year at which the physical, emotional, and intellectual cycles peak, respectively. The value d is the given date and may be smaller than any of p, e, or i. All values are non-negative and at most 365, and you may assume that a triple peak will occur within 21252 days of the given date. The end of input is indicated by a line in which p = e = i = d = -1.

Output

For each test case, print the case number followed by a message indicating the number of days to the next triple peak, in the form: 

Case 1: the next triple peak occurs in 1234 days. 

Use the plural form ``days'' even if the answer is 1.

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


題意:

人自出生起就有體力,情感和智力三個生理週期,分別為23,28和33天。一個週期內有一天為峰值,在這一天,人在對應的方面(體力,情感或智力)表現最好。通常這三個週期的峰值不會是同一天。現在給出三個日期,分別對應於體力,情感,智力出現峰值的日期。然後再給出一個起始日期,要求從這一天開始,算出最少再過多少天后三個峰值同時出現。

思路:

CRT模板題

中國剩餘定理,本題難點不在程式設計,而是分析題目並轉化為數學公式

要引入本題解法,先來看一個故事 “韓信點兵”:
      傳說西漢大將韓信,由於比較年輕,開始他的部下對他不很佩服。有一次閱兵時,韓信要求士兵分三路縱隊,結果末尾多2人,改成五路縱隊,結果末尾多3人,再改成七路縱隊,結果又餘下2人,後來下級軍官向他報告共有士兵2395人,韓信立即笑笑說不對(因2395除以3餘數是1,不是2),由於已經知道士兵總人數在2300~2400之間,所以韓信根據23,128,233,------,每相鄰兩數的間隔是105(3、5、7的最小公倍數),便立即說出實際人數應是2333人(因2333=128+20χ105+105,它除以3餘2,除以5餘3,除以7餘2)。這樣使下級軍官十分敬佩,這就是韓信點兵的故事。 

 

 韓信點兵問題簡化:已知 n%3=2,  n%5=3,  n%7=2,  求n。 


  再看我們這道題,讀入p,e,i,d 4個整數

已知(n+d)%23=p;   (n+d)%28=e;   (n+d)%33=i ,求n 。 

兩道題是一樣的。但是韓信當時計算出結果的? 
 韓信用的就是“中國剩餘定理”,《孫子算經》中早有計算方法,大家可以查閱相關資料。 
“韓信點兵”問題計算如下: 

因為n%3=2, n%5=3, n%7=2 且 3,5,7互質 (互質可以直接得到這三個數的最小公倍數)

令x= n%3=2 , y= n%5=3 ,z= n%7=2
      使5×7×a被3除餘1,有35×2=70,即a=2; 
       使3×7×b被5除餘1,用21×1=21,即b=1; 
       使3×5×c被7除餘1,用15×1=15,即c=1。 
那麼n =(70×x+21×y+15×z)%lcm(3,5,7) = 23 這是n的最小解

 而韓信已知士兵人數在2300~2400之間,所以只需要n+i×lcm(3,5,7)就得到了2333,此時i=22

同樣,這道題的解法就是: 

已知(n+d)%23=p;   (n+d)%28=e;   (n+d)%33=i 
       使33×28×a被23除餘1,用33×28×8=5544; 
       使23×33×b被28除餘1,用23×33×19=14421; 
       使23×28×c被33除餘1,用23×28×2=1288。 
      因此有(5544×p+14421×e+1288×i)% lcm(23,28,33) =n+d 

又23、28、33互質,即lcm(23,28,33)= 21252;
      所以有n=(5544×p+14421×e+1288×i-d)%21252

本題所求的是最小整數解,避免n為負,因此最後結果為n= [n+21252]% 21252
那麼最終求解n的表示式就是:

n=(5544*p+14421*e+1288*i-d+21252)%21252;

當問題被轉化為一條數學式子時,你會發現它無比簡單。。。。直接輸出結果了。

程式碼:
#include <iostream>  
#include <string.h>  
#include <stdio.h>  
using  namespace  std;

const int N=10010;
int a[N],m[N];

void extgcd(int a, int b, int &x, int &y)  {  
  if(b == 0){  
  	x = 1; y = 0;  
    return;  
  }  
  extgcd(b, a % b, x, y);  
  int tmp = x;  
  x = y;  
  y = tmp - (a / b) * y;  
}  
  
int CRT(int a[],int m[],int n){//x ≡ a[i] (mod m[i])
  int M = 1;  
  int ans = 0;  
  for(int i=1; i<=n; i++)  
    M *= m[i];  
  for(int i=1; i<=n; i++){  
    int x, y;  
    int Mi = M / m[i];  
    extgcd(Mi, m[i], x, y); //Mi模mi的逆元
    ans = (ans + Mi * x * a[i]) % M;  
  }  
  if(ans < 0) ans += M;  
  return ans;  
} 

int main(){
	int p,i,e,d,kase=1;
	while(cin>>p>>i>>e>>d){
		if(p==-1 && i==-1 && e==-1 && d==-1)break;
		a[1]=p;
		a[2]=i;
		a[3]=e;
		m[1]=23;
		m[2]=28;
		m[3]=33;
		int ans=CRT(a, m, 3);
		if(ans<=d)ans+=21252;
		printf("Case %d: the next triple peak occurs in %d days.\n", kase++, ans-d);
	}
	return 0;
} 

中國剩餘定理(CRT)的表述如下

設正整數兩兩互素,則同餘方程組

                             

有整數解。並且在模下的解是唯一的,解為

                               

其中,而的逆元。