[CF1097D] Makoto and a Blackboard

[CF1097D] Makoto and a Blackboard - dp,质因数分解

Description

给定 n,k,一共有 k 次操作,每次会把 n 等概率变成 n 的某个约数。求操作 k 次后 n 的期望是多少。

Solution

(h[i][j]) 表示 (n=i, k=j) 的结果

每个质因子的贡献实际上是独立的,反应在次数上就是相乘的关系

因此,每个质因子分别贡献,总答案为乘积

现在对于每个质因子分别算即可

对于 p,设 (f[i][j]) 表示 (n=p^i, k=j) 的结果,那么 (f[i][j]=frac {1}{i+1} sum_{k=0}^j f[k][j-1])

#include <bits/stdc++.h>
using namespace std;

#define int long long
const int mod = 1e9 + 7;
int f[60][10005];

int qpow(int p, int q)
{
    return (q & 1 ? p : 1) * (q ? qpow(p * p % mod, q / 2) : 1) % mod;
}

int solve(int p, int i, int j)
{
    if (f[i][j])
        return f[i][j];
    if (i == 0)
        return f[i][j] = 1;
    if (j == 0)
        return f[i][j] = qpow(p, i);
    f[i][j] = 0;
    for (int k = 0; k <= i; k++)
        f[i][j] += solve(p, k, j - 1);
    return f[i][j] = f[i][j] % mod * qpow(i + 1, mod - 2) % mod;
}

signed main()
{
    ios::sync_with_stdio(false);

    int n, k;
    cin >> n >> k;
    int ans = 1;
    for (int i = 2; i * i <= n; i++)
        if (n % i == 0)
        {
            int cnt = 0;
            while (n % i == 0)
                n /= i, ++cnt;
            memset(f, 0, sizeof f);
            ans *= solve(i, cnt, k);
            ans %= mod;
        }
    memset(f, 0, sizeof f);
    if (n > 1)
        ans *= solve(n, 1, k);
    ans %= mod;
    cout << ans << endl;
}
原文地址:https://www.cnblogs.com/mollnn/p/14408267.html