題目
假設今天是星期日,那么過a^b天之后是星期幾?
?
【輸入】
兩個正整數a,b,中間用單個空格隔開。0<a≤100,0<b≤10000。
?
【輸出】
一個字符串,代表過a^b天之后是星期幾。
?
其中,Monday是星期一,Tuesday是星期二,Wednesday是星期三,Thursday是星期四,Friday是星期五,Saturday是星期六,Sunday是星期日。
?
【輸入樣例】
3 2000
?
【輸出樣例】
Tuesday
假設今天是星期日,那么過a^b天之后是星期幾?
?
【輸入】
兩個正整數a,b,中間用單個空格隔開。0<a≤100,0<b≤10000。
?
【輸出】
一個字符串,代表過a^b天之后是星期幾。
?
其中,Monday是星期一,Tuesday是星期二,Wednesday是星期三,Thursday是星期四,Friday是星期五,Saturday是星期六,Sunday是星期日。
?
【輸入樣例】
3 2000
?
【輸出樣例】
Tuesday
?
?
?
?
01
題目分析
? ? 對于這道題,直觀的想法是求出a^b的值,然后用這個值對7取模,就能知道是星期幾了。但是注意看a和b的取值范圍,a^b的值會是一個非常大的值,遠超出數值的表達范圍了,所以我們要用到模運算的一些性質。
?
1. 模運算的定義
? ? 模運算是基于整除的概念,給定兩個整數a和m(m不為0),a除以m的余數記作a mod m,滿足關系式a = k*m + r,其中k是整數(稱為商),r是滿足0 <= r < m的余數。
?
2. 模運算的分配律:
(a + b) mod m = [(a mod m) + (b mod m)] mod m
(a * b) mod m=[(a mod m) * (b mod m)] mod m
?
模運算的分配律允許我們在進行乘法運算時,不必等待所有乘數相乘之后再取模,而是可以在每一步乘法之后立即取模,最終結果仍然保持一致。
?
舉例說明
? ? 假設我們要計算 3456789 × 9876543對于模100的結果,直接計算乘積將會得到一個非常大的數字,但利用模運算的分配律,我們可以分步進行:
?
?? ???? ?首先,3456789 mod 100 = 89,9876543 mod 100=43。
?? ???? ?然后,計算這兩個余數的乘積:89 * 43 = 3827
?? ???? ?最后,對乘積取模:3827 mod 100 = 27;
?
因此,利用余數的這一性質,我們可以在不直接計算大數冪的情況下高效地求解(a^b) mod m的問題,這對于處理周期性問題(如本題中的星期計算)極為有用。這種方法不僅在數學上嚴謹,而且在計算機科學和密碼學等領域有著廣泛的應用。
?
?
?
?
02
代碼
?
#include <iostream>#include <string>using namespace std;
int main() { ? ?int a, b; ? ?cin >> a >> b; ? ? ? ?// 一周的天數 ? ?const int MOD = 7; ? ?int result = 1;
?? ?// 逐步計算 a^b % 7 ? ?for (int i = 0; i < b; i++) { ? ? ? ?result *= a; ? ? ? ?result %= MOD; // 每次對7取余,結果用于判斷星期幾 ? ?} ? ? ? ?// 從Sunday開始,對應的天數 ? ?string week_days[7] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; ? ? ? ?// 輸出結果 ? ?cout << week_days[result] << endl; ? ? ? ?return 0;}
對于代碼中,為什么可以用累乘之后再取模的方法,最后就能得到(a^b) mod 7的值,這里同學們可以自己利用分配律推演一下,比如輸入的是8和2,那么兩次for循環后,得到的計算結果如下:
?
(8 % 7 * 8 ) % 7?
?
根據分配律,可以進一步轉化:
((8 % 7) % 7 * 8 %7 ) % 7??
?
因為 (8 % 7) % 7 其實就等于 (8 % 7),所以可以進一步轉化:
( 8 % 7 * 8 %7 ) % 7
?
也就是 ( 8 * 8) % 7 ,即8^2 mod 7
?