codeforces#1097 D. Makoto and a Blackboard(dp+期望)

题意:现在有一个数写在黑板上,它以等概率转化为它的一个约数,可以是1,问经过k次转化后这个数的期望值

题解:如果这个数是一个素数的n次方,那么显然可以用动态规划来求这个数的答案,否则的话,就对每个素因数求答案,再相乘

参考博客:https://www.cnblogs.com/birchtree/p/10234203.html

ac代码:

#include<bits/stdc++.h>
#define ll long long
#define  pa pair<int,int>
using namespace std;
const int maxn=100+10;
const int mod=1e9+7;
ll po[70],dp[10000+10][70];
int m;
ll qpow(ll x,ll n)
{
    ll res=1,b=x;
    while(n)
    {
        if(n&1)res=res*b%mod;
        b=b*b%mod;
        n/=2;
        //cout<<<<endl;
    }
    return res;
}
ll solve(int a,ll b)
{
    memset(dp,0,sizeof(dp));
    dp[0][a]=1;
    for(int i=1;i<=m;i++)
        for(int j=0;j<=a;j++)
            for(int k=j;k<=a;k++)
            dp[i][j]=(dp[i][j]+dp[i-1][k]*po[k+1])%mod;
    ll res=0;
    for(int i=0;i<=a;i++)
        res=(res+dp[m][i]*qpow(b,i)%mod)%mod;
    return res;
}
int main()
{
    ll ans=1,n;
    for(int i=1;i<70;i++)
        po[i]=qpow(i,mod-2);
    scanf("%lld %d",&n,&m);
    for(ll i=2;i*i<=n;i++)
    {
        if(n%i==0)
        {
            int k=0;
            while(n%i==0)
            {
                //cout<<1<<endl;
                k++;
                n/=i;
            }
            ans=ans*solve(k,i)%mod;
        }
    }
    if(n!=1)ans=ans*solve(1,n)%mod;
    printf("%lld\n",ans);
    return 0;
}

  

猜你喜欢

转载自www.cnblogs.com/carcar/p/10274060.html