问题题意:
给出两个数A、B (0<=A,B<=50000000),求出A^B的所有因子的和。
相关知识:
1、逆元
2、整数唯一分解定理
对于任意正整数都有且只有一种方式写出其素因子的乘积表达式,即:
A = (p1^k1) * (p2^k2) * (p3^k3) * ... ... * (pn^kn) 其中 pi 均为素数。
3、约束和公式
对于已经分解的整数 A = (p1^k1) * (p2^k2) * (p3^k3) * ... ... * (pn^kn)
A 的所有因子之和为:
Sum = ( p1^0 + p1^1 + ... + p1^k1)*(p2^0 + p2^1 + ... + p2^k2)* ... *(pn^0 + pn^1 + ... + pn^kn)
解题步骤:
1、对A进行素因子分解
对2不断取模…直到a%2 != 0 时结束,继续对3取模,直到a%3 != 0 时结束……
A = (p1^k1) * (p2^k2) * (p3^k3) * ... ... * (pn^kn)
可得 A^B = p1^(k1*B) * p2^(k2*B) * p3^(k3*B) * ... ... * pn^(kn*B)
2、根据分解出的式子进行求和(方法多种)
代码(参考数学一本通):
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<map>
#include<iterator>
#include<set>
using namespace std;
typedef long long Lint;
typedef unsigned long long ULint;
const double pi=atan(1.)*4.;
const int max_n=1e5+1000;
const Lint mod=9901;
Lint p[100010];
Lint k[100010];
Lint prime[100010];
Lint cnt;
bool flag[100010];
void Init(){
flag[1]=true;
cnt=0;
for(Lint i=2;i<100000;i++){
if(flag[i]) continue;
else prime[cnt++]=i;
for(Lint j=2*i;j<100000;j+=i){
flag[j]=true;
}
}
}
Lint poww(Lint a,Lint b){
Lint res=1,base=a%mod;
while(b){
if(b&1)
res*=base;
res%=mod;
base*=base;
base%=mod;
b>>=1;
}
return res%mod;
}
Lint fun(Lint pp,Lint nn){
if(nn==0) return 1;
if(nn%2==1)
return (fun(pp,nn/2)*(1+poww(pp,nn/2+1)))%mod;
else
return (fun(pp,nn/2-1)*(1+poww(pp,nn/2+1))+poww(pp,nn/2))%mod;
}
void solve(Lint a,Lint b){
if(a==0&&b!=0)
{cout<<0<<endl;return;}
Lint n=0;
for(Lint i=0;i<cnt&&prime[i]*prime[i]<=a;i++){
Lint f=0;
while(a%prime[i]==0){
f=1;
p[n]=prime[i];
k[n]++;
a/=prime[i];
}
if(f) n++;
if(a==1) break;
}
if(a!=1){
p[n]=a;
k[n++]=1;
}
for(Lint i=0;i<n;i++){
k[i]*=b;
}
Lint res=1;
for(Lint i=0;i<n;i++){
res=(res*(fun(p[i],k[i])%mod))%mod;
}
cout<<res<<endl;
}
int main(){
Init();
Lint a,b;
cin>>a>>b;
solve(a,b);
return 0;
}