用中國剩餘定理解 POJ1006
http://poj.org/problem?id=1006,大意是每個人在一生中都有三個生理迴圈:身體,情緒和智力。這三個生理迴圈的週期分別是23,28和33天。在這23,28和33天內,這三個生理迴圈都會有一個頂點,在頂點,人們在身體,情緒和智力方面都會有更好的表現。
因為這三個生理迴圈有不同的週期,所以他們到達頂點的時間往往也是不同的。現在要求找出這三個頂點同時出現的時間點。
輸入:
一共有很多行,每行包含四個數字:p,e,i,d. p,e i分別表示今年出現的身體,情緒和智力頂點的日子(可能不是第一個),d表示給定的日期,可能比p,e,i要小。輸入以p = e =i =d =-1結束。
輸出:
輸出下一個頂點日距離給定日子d的距離。以這樣的形式:
Case 1:the next triple peak occurs in 1234 days.
這實際上是中國剩餘定理的一個應用。中國剩餘定理,又稱孫子定理,取自<<孫子算經>>中的“物不知數”問題:有物不知其數,三個一數餘二,五個一數餘三,七個一數又餘二,問該物總數幾何?
就是說一個數用三除餘二,用五除餘三,用七除用餘二,問這個數是幾。
解法如下:
1.先找到35(5 * 7)的倍數,要求除三餘1, 這裡可以看出最小是70
2. 找到 21(3 * 7)的倍數,要求除五餘1, 這裡最小是21,
3. 找到15(3 * 5)的倍數,要求除7餘1, 這裡最小是15
用70 * 2 + 21* 3 + 15 * 2 = 233,233 %(3 * 5 * 7) = 23,23是最小的解,實際上23 + (3*5*7)*k ,k >= 0都是題目的解。
為什麼這個演算法是可行的呢? 對於三個兩兩互質的數字, i, j , k,我們有gcd(i,j) = gcd(i,k) = gcd(j,k) = 1. 我們令M1 = j * k, ,M2 = i * k, M3 = i * j,必然存在t1,t2,t3
- t1 * M1 = 1 (mod i)
- t2 * M2 = 1 (mod j)
- t3 * M3 = 1(mod k)
t1,t2,t3分別稱作M1,M2,M3的逆元。
假如有一個數餘i等於a1, 餘j等於 a2, 餘k等於 a3,那麼有
- a1 * t1 * M1 = a1(mod i)
- a2 * t2 * M2 = a2(mod j)
- a3 * t3 * M3 = a3(mod k)
那麼(a1 * t1 * M1 + a2 * t2 * M2 + a3 * t3 * M3) % i = (a1 * t1 * M1) % i + 0 + 0 = a1(因為M2和M3都是i的倍數,所以餘i得0)
(a1 * t1 * M1 + a2 * t2 * M2 + a3 * t3 * M3) % j = 0 + (a2 * t2 * M2) % j + 0 = a1(因為M1和M3都是j的倍數,所以餘j得0)
(a1 * t1 * M1 + a2 * t2 * M2 + a3 * t3 * M3) % k = 0 + 0 + (a3 * t3 * M3) % k = a1(因為M1和M2都是k的倍數,所以餘k得0)
可以看出(a1 * t1 * M1 + a2 * t2 * M2 + a3 * t3 * M3) 是一個解。又因為 i * j * k是可以被i,j,k三者整除,所以
(a1 * t1 * M1 + a2 * t2 * M2 + a3 * t3 * M3) + (i * j * k)* n,n >= 0都是問題的解。
poj 1006考察的就是對這個定理的瞭解程度。所以剩下的問題就是如何求解t1, t2和t3使得
t1 * M1 = 1 (mod i)t2 * M2 = 1 (mod j)t3 * M3 = 1(mod k)這一般可由擴充套件歐幾里得演算法解除,對於本題,可以事先用暴力搜尋找出這些值,t1 = 5544, t2 = 14421, t3 = 1428,剩下的問題就是套用剩餘定理的公式了。
最後貼上accept的程式碼,僅供拋磚引玉之用:
#include <stdio.h>
#define ALL_PRODUCTION (23 * 28 * 33)
int main()
{
int p,e,i,d,k;
for(int j = 0;;j++)
{
scanf("%d %d %d %d",&p,&e,&i,&d);
if(p == -1)
break;
else
{
k = 5544 * p + 14421 * e + 1288 * i;
k = k % ALL_PRODUCTION;
k = k - d;
if(k <= 0)
{
k += ALL_PRODUCTION;
}
printf("Case %d: the next triple peak occurs in %d days.\n",j + 1, k);
}
}
return 0;
}
相關文章
- 中國剩餘定理
- 中國剩餘定理詳解
- 中國剩餘定理(構造)
- 中國剩餘定理(個人筆記)筆記
- 擴充套件中國剩餘定理套件
- 擴充套件中國剩餘定理詳解套件
- Strange Way to Express Integers(中國剩餘定理+不互質)Express
- JavaScript 剩餘運算子JavaScript
- 擴充套件中國剩餘定理(EXCRT)學習筆記套件筆記
- X問題(中國剩餘定理+不互質版應用)hdu1573
- 檢視Win10啟用剩餘時間Win10
- HDU1788Chinese remainder theorem again(中國剩餘定理 簡單)REMAI
- boot分割槽剩餘空間不足boot
- parted掛載硬碟剩餘空間硬碟
- hdu 1792 A New Change Problem 剩餘系
- 遊戲物品如何定價?談談遊戲中的消費者剩餘遊戲
- linux檢視剩餘磁碟空間Linux
- Codeforces 687B. Remainders Game[剩餘]REMAIGAM
- MYSQL中查詢資料庫設定多大,剩餘空間是多少(轉)MySql資料庫
- 數論入門基礎(同餘定理/費馬小定理/擴充套件歐幾里德演算法/中國剩餘定理)套件演算法
- ES6 - 函式與剩餘運算子函式
- 設定清帳剩餘專案基準日期以原始專案為準-轉
- Bell(hdu4767+矩陣+中國剩餘定理+bell數+Stirling數+歐幾里德)矩陣
- 大宇擬出售北軟剩餘股份及《仙劍》IP
- 阿姆斯特丹機場允許旅客用剩餘的歐元兌換加密貨幣加密
- 前端-如何始終平均分配剩餘空間前端
- 剩餘運算子與展開運算子的區別
- ES6箭頭函式的剩餘引數函式
- LINUX檢視目錄剩餘空間的命令Linux
- 『Android』 獲取檔案系統剩餘空間Android
- 獲取波場(Tron)錢包TRX、USDT餘額和剩餘頻寬、能量 - 筆記筆記
- oracle 剩餘表空間查詢慢,解決辦法Oracle
- 二次剩餘Cipolla演算法學習筆記演算法筆記
- js獲取當前月份剩餘的天數程式碼JS
- 檢視asm磁碟組剩餘空間的正確方法ASM
- 獲取linux可用記憶體 剩餘記憶體Linux記憶體
- linux下檢視分割槽資訊和剩餘空間大小Linux
- NumPyCookbook帶註釋原始碼四、連線NumPy與剩餘世界原始碼