原题: http://codeforces.com/problemset/problem/1097/D
题意: 有一个1e15内的数,每次会随机变成一个它的因子,问k次变化后的结果的期望。
解析:
对于一个数 ,可以看成质因子幂的形式,设它的一个质因子 ,有 ,那么显然下一次变化 有等概率变成 ,那么这个东西是很好维护的。所以只需要将这个数质因子分解出来,对于每个质因子做 次即可。
化一下也可以证明 ,当然逆元在乘除方面是一定化解可行的。
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define debug(i) printf("->%d\n",i)
LL n,k;
const LL maxn=4e7;
const LL maxm=25e5;
const LL mod = 1e9+7;
vector<LL>num;
vector<LL>dp[maxm];
bool vis[maxn];
LL pri[maxm],cnt;
LL inv[maxm];
void init(){
//逆元
inv[1]=1;
for(LL i=2;i<maxm;i++){
inv[i]=(mod-mod/i)*inv[mod%i]%mod;
}
//素数
for(LL i=2;i<maxn;i++){
if(!vis[i]){
pri[++cnt]=i;
}
for(LL j=1;j<=cnt&&pri[j]*(LL)i<maxn;j++){
vis[pri[j]*(LL)i]=1;
if(!(i%pri[j]))break;
}
}
//处理
LL en=(LL)(sqrt((double)n))+1ll;
for(LL i=1;i<=cnt&&pri[i]<=min(n,en);i++){
LL ct=0;
while(n%pri[i]==0){
ct++;n/=pri[i];
}
if(ct){
num.push_back(pri[i]);
while(ct--){
dp[num.size()-1].push_back(0);
}
dp[num.size()-1].push_back(1);
}
}
if(n>1){
num.push_back(n);
dp[num.size()-1].push_back(0);
dp[num.size()-1].push_back(1);
}
}
LL i,j,siz;
LL sum,p;
LL ans=1;
void solve(){
for(i=0;i<num.size();i++){
for(j=1;j<=k;j++){
sum=0;
for(siz=dp[i].size()-1;siz>=0;siz--){
sum=(sum+dp[i][siz]*inv[siz+1])%mod;
dp[i][siz]=sum;
}
}
p=0;
sum=1;
for(siz=0;siz<dp[i].size();siz++){
p=(p+sum*dp[i][siz])%mod;
sum=sum*num[i]%mod;
}
ans=ans*p%mod;
}
printf("%lld\n",ans);
}
int main(){
scanf("%lld%lld",&n,&k);
init();
solve();
}