poj sumdiv(数学)

将a进行质因数分解,则

        a=(p1^k1)*(p2^k2)*...*(pn^kn);

   故  a^b= p1^(a1*B) * p2^(a2*B) *...* pn^(an*B);

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

sum=(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<string.h>
#include<cstdio>
const int N=7100;
#define M 9901
int e[N],factor[N];
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)        //如果k是奇数     
		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,x=0;
	__int64 ans;
	memset(e,0,sizeof(e));
	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++)
	{
		__int64 tmp=get(factor[i],e[i]*b);
		ans=(ans*tmp)%M;
	}
	printf("%I64d\n",ans);
	return 0;
}

转载于:https://www.cnblogs.com/You-Change/p/3527932.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值