您的位置:首页 > 其它

POJ 1845 Sumdiv

2011-02-25 20:46 225 查看
将a进行质因数分解,则a^b=(p1^k1)*(p2^k2)*...*(pn^kn)

根据公式,所有因子之和为

(1+p1+p1^2+...p1^k1)*(1+p2+p2^2+...p2^k2)*...*(1+pn+pn^2+...+pn^kn)

计算1+p+p^2+...p^n可以利用二分进行加速

当n为奇数时,例如n=5

则1+p+p^2+p^3+p^4+p^5=(1+p+p^2)+p^3*(1+p+p^2)=(1+p+p^2)*(1+p^3)

可以发现1+p+p^2+...p^n=(1+p+p^2+...+p^(k/2))*(1+p^(k/2+1))

当n为偶数时,例如n=4

则1+p+p^2+p^3+p^4=(1+p)+p^3*(1+p)+p^2=(1+p)*(1+p^3)+p^2

可以发现1+p+p^2+...p^n=(1+p+p^2+...+p^(k/2-1))*(1+p^(k/2+1))+p^(k/2)

代码:

#include<iostream>
#include<memory.h>
#include<cstdio>
using namespace std;
const int MAXN=7100;
#define M 9901
int e[MAXN],factor[MAXN];
int cnt;
__int64 a,b;
__int64 pow(__int64 p,__int64 n)//计算p^n
{
__int64 ret=1,s=p;
while(n)
{
if(n&1)
ret=(ret*s)%M;
s=(s*s)%M;
n>>=1;
}
return ret;
}
__int64 get(__int64 p,__int64 k)//计算1+p+p^2+...+p^k
{
if(k==0)
return 1;
if(k&1)
return ((1+pow(p,k/2+1))%M*get(p,k/2)%M)%M;
else
return ((1+pow(p,k/2+1))%M*get(p,k/2-1)%M+pow(p,k/2)%M)%M;
}
int main()
{
int i,j,x;
__int64 ans;
memset(e,0,sizeof(e));
x=0;
scanf("%I64d%I64d",&a,&b);
for(i=2;i*i<=a;i++)
{
if(a%i==0)
{
factor[x]=i;
while(a%i==0)
{
a/=i;
e[x]++;
}
x++;
}
}
if(a>1)
{
factor[x]=a;
e[x++]=1;
}
ans=1;
for(i=0;i<x;i++)//x个因子
{
__int64 tmp=get(factor[i],e[i]*b);
//cout<<factor[i]<<" "<<e[i]<<endl;
ans=(ans*tmp)%M;
//cout<<ans<<endl;
}
cout<<ans<<endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: