D. Makoto and a Blackboard(积性函数+DP)
题目链接:http://codeforces.com/contest/1097/problem/D
题目大意:给你n和k,每一次可以选取n的因子代替n,然后问你k次操作之后,每个因子的期望。
具体思路:对于给定的n,我们可以将n转换为,n=p1^(k1)*p2^(k2)*p3^(k3)......,然后我们求期望的时候,我们可以求每个因子的期望,然后再将每个因子的期望相乘就可以了(积性函数的性质)。
然后我们使用一个dp数组,dp[i][j]代表某一个因子,经过i次操作,出现j次的概率。
数学期望:离散随机变量的一切可能值工与对应的概率P的乘积之和称为数学期望
AC代码:
#include<bits/stdc++.h>
using namespace std;
# define LL long long
# define inf 0x3f3f3f3f
const int maxn = 1e5+100;
const int mod = 1e9+7;
LL dp[maxn][60],inv[maxn];
LL n, k;
LL cal(LL num,LL tim)
{
for(LL i=1; i<tim; i++)
dp[0][i]=0;
dp[0][tim]=1;
for(LL i=1; i<=k; i++)
{
for(LL ii=0; ii<=tim; ii++)
{
dp[i][ii]=0;
for(LL iii=ii; iii<=tim; iii++)
dp[i][ii]=(dp[i][ii]+dp[i-1][iii]*inv[iii]%mod)%mod;
}
}
LL t1=0,t2=1;
for(LL i=0; i<=tim; i++)
{
t1=(t1+dp[k][i]*t2%mod)%mod;
t2=t2*num%mod;
}
return t1%mod;
}
int main()
{
inv[1]=1;
for (LL i=2; i<=60; i++)
inv[i]=(mod-mod/i)*inv[mod%i]%mod;
scanf("%lld %lld",&n,&k);
LL ans=1;
for(LL i=2; i*i<=n; i++)
{
int num=0;
while(n%i==0)
{
n/=i;
num++;
}
if(num==0)
continue;
ans=ans*cal(i,num)%mod;
}
if (n!=1)
ans=ans*cal(n,1)%mod;
printf("%lld\n",ans);
return 0;
}