Sumdiv

POJ

题意:求\(A^B\)的所有约数之和$ \mod 9901(1<=A,B<=5*10^7)$

分析:把A分解质因数即\(A=p_1^{c_1}*p_2^{c_2}*...*p_m^{c_m}\),则\(A^B=p_1^{B*c_1}*p_2^{B*c_2}*...*p_m^{B*c_m}\),则\(A^B\)的所有约数之和就是\((1+p_1+p_1^2+...+p_1^{B*c_1})*(1+p_2+p_2^2+...+p_2^{B*c_2})*...*(1+p_m+p_m^2+...+p_m^{B*c_m})\).然后对于每一组用分治法来求即可.

具体来说,要求\(sum(p,c)=a+p+p^2+...+p^c\)?若c为奇数,\(sum(p,c)=(1+p^{\frac{c+1}{2}})*sum(p,\frac{c-1}{2})\);若c为偶数,\(sum(p,c)=(1+p^{\frac{c}{2}})*sum(p,\frac{c}{2}-1)+p^c\).

注意有些乘的地方要long long,然后不知道为什么竟然不需要特判...

//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define LL long long
using namespace std;
inline int read() {
    int x=0,o=1;char ch=getchar();
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')o=-1,ch=getchar();
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*o;
}
const int mod=9901;
int A,B,m,p[100005],c[100005];
inline void Divide(int n){
	m=0;
	/*if(n==2||n==3){
		m=1;p[m]=n;c[m]=1;
		return;
	}*/
	for(int i=2;i*i<=n;++i){
		if(n%i==0){
			p[++m]=i;c[m]=0;
			while(n%i==0)n/=i,c[m]++;
		}
	}
	if(n>1)p[++m]=n,c[m]=1;
	return;
}
inline LL ksm(int a,int b){
	LL cnt=1;
	while(b){
		if(b&1)cnt=(LL)cnt*a%mod;
		a=(LL)a*a%mod;
		b>>=1;
	}
	return cnt;
}
inline int sum(LL p,LL c){
	if(c==0)return 1;
	if(c%2==1)return((1+ksm(p,(c+1)/2))*sum(p,(c-1)/2))%mod;
	if(c%2==0)return((1+ksm(p,c/2))*sum(p,(c/2)-1)+ksm(p,c))%mod;
}
int main(){
	while(scanf("%d%d",&A,&B)!=EOF){
		//if(A==0||A==1){printf("%d\n",A);continue;}
		//if(B==0){puts("1");continue;}
		int ans=1;Divide(A);
		for(int i=1;i<=m;++i)
			ans=(ans*sum(p[i],B*c[i]))%mod;
		printf("%d\n",ans);
	}
    return 0;
}

posted on 2019-07-22 20:29  PPXppx  阅读(155)  评论(0编辑  收藏  举报