Makoto and a Blackboard
题解
我们定义为n操作k次的期望个数,那么,其中x为d的约数个数。
而n的约数个数可以在的时间内求出,于是总时间就是。
对于一个质数n,答案是。
那么对于,其中p为质数。那么就可以用dp来解决这个问题。
表示经过i次操作,数变为的概率。
可得转移方程式为,
而答案就为。
因为这是一个积性函数,所以可得答案
于是,我们把n分解质因数后的答案乘起来即可。
于是就可以以的时间复杂度求出来了。
源码
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
#define MAXN 1000005
typedef long long LL;
#define int LL
const LL mo=1e9+7;
typedef pair<double,int> pii;
#define gc() getchar()
template<typename _T>
void read(_T &x){
_T f=1;x=0;char s=gc();
while(s>'9'||s<'0'){if(s=='-')f=-1;s=gc();}
while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=gc();}
x*=f;
}
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
int n,m,prime[MAXN],cntp,ans,sum;
int dis[MAXN],dp[10005][50],inv[65];
void init(int x){
for(int i=2;i*i<=x;i++){
if(x%i==0)prime[++cntp]=i;
while(x%i==0)x/=i,++dis[cntp];
}
if(x!=1)prime[++cntp]=x,dis[cntp]++;
}
int qkpow(int a,int s){
int t=1;
while(s){
if(s&1)t=t*a%mo;
s>>=1;a=a*a%mo;
}
return t;
}
signed main(){
read(n);read(m);init(n);ans=1;
for(int i=1;i<=60;i++)inv[i]=qkpow(i,mo-2);
for(int T=1;T<=cntp;T++){
memset(dp,0,sizeof(dp));
dp[0][dis[T]]=1;int sum=0;
for(int i=1;i<=m;i++)
for(int j=0;j<=dis[T];j++)
for(int k=j;k<=dis[T];k++)
dp[i][j]=(dp[i-1][k]*inv[k+1]%mo+dp[i][j])%mo;
for(int i=0;i<=dis[T];i++){
sum=(sum+dp[m][i]*qkpow(prime[T]%mo,i)%mo)%mo;
//printf("%d %d:%d\n",m,i,dp[m][i]);
}
ans=ans*sum%mo;
}
printf("%lld",ans);
return 0;
}