POJ1845 Sumdiv [數論,逆元]
阿新 • • 發佈:2018-06-22
ide org algo tab 之前 BE bmi nbsp ron
The natural divisors of 8 are: 1,2,4,8. Their sum is 15.
15 modulo 9901 is 15 (that should be output).
題目傳送門
Sumdiv
Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 26041 | Accepted: 6430 |
Description
Consider two natural numbers A and B. Let S be the sum of all natural divisors of A^B. Determine S modulo 9901 (the rest of the division of S by 9901).Input
The only line contains the two natural numbers A and B, (0 <= A,B <= 50000000)separated by blanks.Output
The only line of the output will contain S modulo 9901.Sample Input
2 3
Sample Output
15
Hint
2^3 = 8.The natural divisors of 8 are: 1,2,4,8. Their sum is 15.
15 modulo 9901 is 15 (that should be output).
Source
Romania OI 2002
分析:
題意就是求A^B在mod 9901下的約數和。
之前遇到過一個一模一樣的題,直接分解質因數,把每一個質因數按照費馬小定理對9901-1取模然後直接暴力計算就過了,但是在這裏死活過不了。然後稍微推了一下發現這麽做有BUG,因為9900不是質數,取模的時候會出錯。
然後翻了一下lyd的書,正解思路了解一下。
同樣先分解質因數,再由約數和定理ans=(1+q1+q1^2+...+q1^(c1*b))*(1+q2+q2^2+...+q2^(c2*b))*...*(1+qn+qn^2+...qn^(cn*b))可得,對於每一個質因數qi,求(1+qi+qi^2+...+qi^(ci*b))時,可以用等比數列的求和公式求,即(qi^(b*ci+1))/(qi-1),但是除法並不滿足取模的分配律,所以就用逆元來代替。也就是求1/(qi-1)在模9901下的逆元。但是要註意,qi-1可能被9901整除,此時不存在逆元。不過可以發現,此時qi mod 9901=1,那麽(1+qi+qi^2+...+qi^(b*ci))=1+1+1+...+1(b*ci+1個1),特判即可。
Code:
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<iostream> 6 #include<iomanip> 7 #include<algorithm> 8 using namespace std; 9 typedef long long ll; 10 const ll mod=9901; 11 const ll N=5e6+7; 12 ll A,B,q[N],f[N],ans,tot,cnt; 13 void fenjie() 14 { 15 for(ll i=2;i*i<=A;i++){ 16 if(A%i==0){ 17 q[++cnt]=i; 18 while(A%i==0){ 19 f[cnt]++;A/=i;} 20 } 21 } 22 if(A>1)q[++cnt]=A,f[cnt]++; 23 } 24 inline ll power(ll x,ll y) 25 { 26 ll ret=1; 27 while(y>0){ 28 if(y&1)ret=(ret*x)%mod; 29 x=(x*x)%mod;y>>=1;} 30 return ret; 31 } 32 void work() 33 { 34 fenjie();ans=1; 35 for(int i=1;i<=cnt;i++){ 36 if((q[i]-1)%mod==0){ 37 ans=(ans*(B*f[i]+1)%mod)%mod; 38 continue;} 39 ll x=power(q[i],B*f[i]+1); 40 x=(x-1+mod)%mod; 41 ll y=power(q[i]-1,mod-2); 42 ans=(ans*x*y)%mod; 43 } 44 printf("%lld",ans); 45 } 46 int main() 47 { 48 cin>>A>>B; 49 work();return 0; 50 }
POJ1845 Sumdiv [數論,逆元]