POJ 1845 Sumdiv 二分+因式分解

来源:互联网 发布:网络电话卡怎么使用 编辑:程序博客网 时间:2024/06/04 18:11

Sumdiv
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两个数,求A^B的所有因数的和,%9901;

首先我们把问题简化:
A的所有因数的和为多少?
因为A=(p1^c1)(p2^c2) ….. *(pn^cn)
接下来就烧脑了:
因为p1 有 c1 个,任选0~c1个都行,用代数式表达就是(p1^0+p1^1+……+p1^c1)
然后把这n个括号连起来,所以A的因子和:
SumA=(p1^0+p1^1+……+p1^c1)* (p2^0+p2^1+……+p2^c2)…… (pn^0+pn^1+……+pn^cn)
而(pn^0+pn^1+……+pn^cn)=
1. cn%2==1 原式 = (pn^0+pn^1+……+pn^(cn/2))*(1+(pn^(cn/2+1)))
2. cn%2==0 和上面类似,具体看我代码。

这样就可以二分解决问题。

AC代码:

#include<cstdio>#define mod 9901long long a,b,ans=1,g;long long qk_pow(int a,int b){    long long tmp=a%mod,ans=1;    while(b){        if(b&1){ ans*=tmp;ans%=mod; }        b>>=1;        tmp=(tmp*tmp)%mod;    }    return ans;}long long count(long long now,long long p){         if(p==0) return 1;                                              if(p%2==1)   return count(now,p/2)*((1+qk_pow(now,p/2+1))%mod)%mod;             else         return (count(now,p/2-1)*((1+qk_pow(now,p/2+1))%mod)+qk_pow(now,p/2)%mod)%mod;}int main(){    scanf("%lld%lld",&a,&b);    for(int i=2;i*i<=a;i++){        if(a%i==0){            g=0;            while(a%i==0){                g++;                a/=i;            }            ans=(count(i,g*b)*ans)%mod;        }    }    if(a>1)    {        g=1;        ans=(count(a,g*b)*ans)%mod;    }    printf("%lld",ans);}
0 0