cogs 2691. Sumdiv
2691. Sumdiv
★★★ 输入文件:sumdiv.in
输出文件:sumdiv.out
简单对比
时间限制:1 s 内存限制:12 MB
【题目描述】
考虑两个自然数A和B.定义S是A ^ B的所有自然因数的总和。确定S模9901的值。
【输入格式】
唯一的行包含由空格分隔的两个自然数A和B(0 <= A,B <= 50000000)。
【输出格式】
输出一行,即S模9901。
【样例输入】
2 3
【样例输出】
15
样例解释:2 ^ 3 = 8。 8的自然因数是:1,2,4,8。他们的和是15。 15模9901是15(应该输出)。
【来源】
POJ1845
/* 题意:求A^B 所有约数(因子)之和mod 9901。 应用质因数分解+约数和公式+逆元+等比数列求和公式 A=p1^k1*p2^k2*...pn^kn A^B=p1^(k1*B)*p2^(k2*B)...pn^(kn*B) 约数和公式:Sum=(1+p1+p1^2+...+p1^k1)*(1+p2+p2^2+...+p2^k2)*(......pk^kn) Sum(A^B)=(1+p1+p1^2+...+p1^k1*B)*(1+p2+p2^2+...+p2^k2*B)*(......pk^kn*B) mod 9901 对于每一个 (1+p1+p1^2+...+p1^k1*B),根据等比数列求和公式为 [1-p1^(1+k1*B)]/(1-p1) mod 9901 根据逆元公式:a/b mod m=(a mod mb )/b 原式= [p1^(k1*B+1)-1] mod [9901*(p1-1)] / (p1-1) */ #include<iostream> #include<cstdio> #include<cstring> using namespace std; #define ll long long #define mod 9901 #define N 10005 int p[N],cnt; ll A,B; bool prime[N]; void Isprime(){ for(int i=2;i<N;i++) if(!prime[i]){ p[++cnt]=i; for(int j=i+i;j<N;j+=i) prime[j]=1; } } ll slow_mul(ll a,ll b,ll m){ ll result=0;a%=m; while(b){ if(b&1){result=(result+a)%m;} b>>=1; a=(a+a)%m; } return result; } ll fast_pow(ll a,ll b,ll m){ ll result=1;a%=m; while(b){ if(b&1)result=slow_mul(result,a,m); b>>=1; a=slow_mul(a,a,m); } return result; } int main(){ freopen("sumdiv.in","r",stdin); freopen("sumdiv.out","w",stdout); //freopen("cola.txt","r",stdin); scanf("%lld%lld",&A,&B); if(A==0){printf("0");return 0;} Isprime(); ll ans=1; for(int i=1;p[i]*p[i]<=A;i++){//质因数分解 if(A%p[i]==0){ int num=0; while(A%p[i]==0)num++,A/=p[i]; ll M=mod*(p[i]-1); ans*=(fast_pow(p[i],num*B+1,M)-1)/(p[i]-1); ans%=mod; } } if(A>1){ ll M=(A-1)*mod; ans*=(fast_pow(A,B+1,M)-1)/(A-1); ans%=mod; } printf("%lld",ans); }