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
",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/letlifestop/p/10262740.html