CF-1097D-Makoto and a Blackboard

这题在比赛的时候耗了我近两个小时,还是没做出来。用到逆元和期望。赛前掌握的不够好,现在看了几位大佬的代码之后把这题补上。

代码参考来源:https://blog.csdn.net/qq_36797743/article/details/85834812

1097D - 20 GNU C++11 Happy New Year! 218 ms 2164 KB
#include "bits/stdc++.h"
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const int MAXK = 1e4 + 5;
const int MOD = 1e9 + 7;
int K, ans = 1;
int inv[55], dp[MAXK][55];
void calc(LL n, int m) {
    printf("%lld %d\n", n, m);
    dp[0][m] = 1;
    // 一开始还在纠结为什么不用memset来置0,后来感觉数组中要用到的元素不多,用for循环应该更快
    for (int i = 0; i < m; i++)
    dp[0][i] = 0;
    for (int i = 1; i <= K; i++) {
        for (int j = 0; j <= m; j++) {
            dp[i][j] = 0;
            for(int k = j; k <= m; k++) {
                // 一次操作之后,n^k可能会变成n^0,n^1,n^2……n^k,总共k+1种可能,所以dp[i][j]要加上1/(k+1)%MOD;
                dp[i][j] = (dp[i][j] + dp[i - 1][k] * 1LL * inv[k + 1]) % MOD;
            }
        }
    }
    int now = 1, res = 0;
    for (int i = 0; i <= m; i++) {
        res = (res + now * 1LL * dp[K][i]) % MOD;
        now = now * n % MOD;
    }
    ans = ans * 1LL * res % MOD;
}
int main() {
    LL N;
    scanf("%lld%d", &N, &K);
    inv[1] = 1;
    // 线性筛求逆元
    for (int i = 2; i < 55; i++) {
        inv[i] = (MOD - MOD / i) * 1LL * inv[MOD % i] % MOD;
    }
    // 分解质因数
    for (int i = 2; i * 1LL * i <= N; i++) {
        if (N % i) {
            continue;
        }
        int cnt = 0;
        while (N % i == 0) {
            cnt++;
            N /= i;
        }
        calc(i, cnt);
    }
    if (N > 1) calc(N, 1);
    printf("%d\n", ans);
    return 0;
}

纪念第一道求期望的题

猜你喜欢

转载自www.cnblogs.com/Angel-Demon/p/10228463.html