CF1097D Makoto and a Blackboard

思路:

概率dp。首先对n进行因子分解得到,然后每个素因子pi,计算经过k次操作之后的期望值Ei,再利用期望的性质把所有Ei乘起来得到最终结果。Ei可以通过概率dp计算,dp[i][j]表示经过i次操作之后出现的概率。

实现:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef long long ll;
 5 
 6 const ll MOD = 1e9 + 7;
 7 
 8 ll dp[10005][60];
 9 
10 ll qpow(ll x, ll n)
11 {
12     ll res = 1;
13     while (n)
14     {
15         if (n & 1) res = res * x % MOD;
16         x = x * x % MOD;
17         n >>= 1;
18     }
19     return res;
20 }
21 
22 ll inv(ll x)
23 {
24     return qpow(x, MOD - 2);
25 }
26 
27 map<ll, int> fac(ll x)
28 {
29     map<ll, int> ans;
30     for (ll i = 2; i * i <= x; i++)
31     {
32         while (x % i == 0)
33         {
34             x /= i;
35             ans[i]++;
36         }
37     }
38     if (x != 1) ans[x] = 1;
39     return ans;
40 }
41 
42 int main()
43 {
44     ll n; int k;
45     while (cin >> n >> k)
46     {
47         map<ll, int> ans = fac(n);
48         ll res = 1;
49         for (auto it: ans)
50         {
51             memset(dp, 0, sizeof dp);
52             ll tmp = it.first; int cnt = it.second;
53             dp[0][cnt] = 1;
54             for (int i = 1; i <= k; i++)
55             {
56                 dp[i][cnt] = dp[i - 1][cnt] * inv(cnt + 1) % MOD;
57                 for (int j = cnt - 1; j >= 0; j--)
58                 {
59                     dp[i][j] = dp[i][j + 1];
60                     dp[i][j] = (dp[i][j] + dp[i - 1][j] * inv(j + 1)) % MOD;
61                 }
62             }
63             ll sum = 0;
64             for (int i = 0; i <= cnt; i++)
65             {
66                 sum = (sum + dp[k][i] * qpow(tmp, i) % MOD) % MOD;
67             }
68             res = res * sum % MOD;
69         }
70         cout << res << endl;
71     }
72     return 0;
73 }
原文地址:https://www.cnblogs.com/wangyiming/p/10229100.html