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;
}