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; }
纪念第一道求期望的题