HDU 1452 Happy 2004
在ACM中,數學題很多,數學也是相當重要的。本題就要用到數學知識,真是書到用時方恨少,大家還是多記數學定理和結論吧。
Consider a positive integer X,and let S be the sum of all positive integer divisors of 2004^X. Your job is to determine S modulo 29 (the rest of the division of S by 29).Take X = 1 for an example. The positive integer divisors of 2004^1 are 1, 2, 3, 4, 6, 12, 167, 334, 501, 668, 1002 and 2004. Therefore S = 4704 and S modulo 29 is equal to 6.
Input The input consists of several test cases. Each test case contains a line with the integer X (1 <= X <= 10000000).
A test case of X = 0 indicates the end of input, and should not be processed.
Output For each test case, in a separate line, please output the result of S modulo 29.
Sample Input
1 10000 0
6 10
分析一下,本題求的是2004^x的約數和對29取模,這裡我們要計算,約數和,下面介紹兩個定理:
①整數唯一分解定理:
一個整數A一定能被分成:A=(P1^K1)*(P2^K2)*(P3^K3).....*(Pn^Kn)的形式。其中Pn為素數。
如2004=(22)*3*167。
那麼2004x=(22x)*(3x)*(167x)。
②約數和公式
對於一個已經被分解的整數A=(P1^K1)*(P2^K2)*(P3^K3).....*(Pn^Kn),
有約數和S=(1+P12+P13+.....P1k1)*.....(1+Pn2+Pn3+.....Pn
(1+P12+P13+.....P1k1)是一個等比數列,化簡為(P1k1+1 -1)/(P1-1).
對於2004^X, 只要求出a=pow(2,2*x+1)-1,b=pow(3,x+1)-1,c=pow(167,x+1)-1即可,使用快速冪取模計算。
所以我們要算的是(a*b/2*c/166)%29,那麼裡面這個除法怎麼處理呢,方法就是取乘法逆元,也就是說令e=2*166%29=9,則(a*b/2*c/166)%29=(a*b*c*e)%29。
下面是程式碼:
#include<cstdio> #define ll long long const int mod=29; ll quickpow(ll a,ll b){ ll ans=1; a=a%mod; while(b){ if(b&1) ans=ans*a%mod; b>>=1; a=a*a%mod; } return ans; } int main() { ll x; while(~scanf("%lld",&x)&&x){ ll a=quickpow(2,2*x+1)-1; ll b=quickpow(3,x+1)-1; ll c=quickpow(167,x+1)-1; printf("%lld\n",(a*b*c*9)%mod); } }
當然,在網上查的時候看有的兄弟找出了規律做,在下實在佩服,可以參考:點選開啟連結
可能有的人不理解上面的除法(a*b/2*c/166)%29=(a*b*c*e)%29取模,其實這也是個推出來的結論,記憶就行了:
(因為這裡a、b、c是取模後的結果,所以不能拿他們直接除2*166,但是如果不取模可以除,但是太大了一定會溢位)
當我們要求(a / b) mod p的值,且 a 很大,無法直接求得a / b的值時,我們就要用到乘法逆元。
滿足 b * k ≡ 1 (mod p) 的 k 的值就是 b 關於 p 的乘法逆元。
我們可以通過求 b 關於 p 的乘法逆元 k,將 a 乘上 k 再模 p,即 (a * k) mod p。其結果與(a / b) mod p等價
(可以用擴充套件歐幾里得)
在下實力有限,歡迎大家指出錯誤,謝謝。