【Luogu】P1593因子和(唯一分解定理,约数和公式)
首先介绍两个定理。
整数唯一分解定理:任意正整数都有且只有一种方式写出素数因子的乘积表达式。
\(A=(p1k1 p2k2 ...... pnkn \)
求这些因子的代码如下
for(int i=2;i*i<=a;++i){ if(!(a%i)){ prime[++num]=i; while(!(a%i)){ a/=i; sum[num]++; } } } if(a!=1){ prime[++num]=a; sum[num]=1; }
约数和公式:对于已经分解的整数A,有A的所有因子和为
\( S= (1+p1+p12+p13+......+p1k1) (1+p2+p22+p23+......+p2k2)........(1+pn+pn2+pn3+......+pnkn) \)
所以局势明朗。用快速幂求出p的k*b次方,然后递归求和。代码如下
long long Sum(long long p,long long n){ if(n==0) return 1; if(n&1) return (Sum(p,n>>1)*(1+Pow(p,(n>>1)+1)))%mod; return (Sum(p,(n>>1)-1)*(1+Pow(p,(n>>1)+1))+Pow(p,n>>1))%mod; }
解题代码如下
#include<cstdio> #include<cctype> #define mod 9901 inline long long read(){ long long num=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-') f=-1; ch=getchar(); } while(isdigit(ch)){ num=num*10+ch-'0'; ch=getchar(); } return num*f; } int prime[10000]; int sum[10000]; int num; long long Pow(long long n,long long i){ if(i==0) return 1; if(i==1) return n%mod; long long ret=Pow(n,i>>1); if(i&1) return (((ret*ret)%mod)*n)%mod; return (ret*ret)%mod; } long long Sum(long long p,long long n){ if(n==0) return 1; if(n&1) return (Sum(p,n>>1)*(1+Pow(p,(n>>1)+1)))%mod; return (Sum(p,(n>>1)-1)*(1+Pow(p,(n>>1)+1))+Pow(p,n>>1))%mod; } int main(){ long long a=read(),b=read(); for(int i=2;i*i<=a;++i){ if(!(a%i)){ prime[++num]=i; while(!(a%i)){ a/=i; sum[num]++; } } } if(a!=1){ prime[++num]=a; sum[num]=1; } int ans=1; for(int i=1;i<=num;++i) ans=(ans*Sum(prime[i],sum[i]*b)%mod)%mod; printf("%d",ans); return 0; }