题目描述
小海喜欢和小鸟玩抽鬼牌,规则如下:小鸟每次有n张牌,其中有m张鬼牌;小海一次抽出一张牌,如果不是鬼牌则移除这张牌,否则小海就输了;当只剩下m张鬼牌时小海赢。
因为小海永远赢不了,所以小鸟修改了规则。如果小海输了,那她可以把鬼牌放回去并继续进行一轮游戏(非鬼牌保持不变),直到她赢为止。每一轮游戏,小鸟都会获得一个愉悦值。假设这轮游戏小海抽到k张非鬼牌,小鸟的愉悦值为(k+1)^q。为了更好的欣赏小海的颜艺,小鸟想知道她的期望愉悦值(mod 998244353)。
输入
一行3个数n,m,q
输出
一个数表示答案
样例输入
4 2 2 456 123 6
样例输出
665496246 32740446
提示
数据范围
10% n=m+1
另外10% n<=8
另外20% q=0;
另外20% n<=1e3
另外 10% q=1
另外 20% n<=1e5
100% m<=n n<=1e6 q<=10
设f[i]表示还剩i张牌的期望愉悦值。
$f[i]=frac{m}{i}(f[i]+1)+sum_{j<i}{frac{i-m}{i}*frac{i-m-1}{i-1}*…*frac{j-m-1}{j+1}*frac{m}{j}*(f[j]+(i-j+1)^q})$
将f[i]挪到左边整理一下可以得到
$f[i]=frac{m}{i-m}(frac{m}{i}+sum_{j<i}{frac{i-m}{i}*frac{i-m-1}{i-1}*…*frac{j-m-1}{j+1}*frac{m}{j}*(f[j]+(i-j+1)^q}))$
这东西可以跑$O(n^2)$的dp了
考虑f[i-1]的转移式子和f[i]的转移式子的区别。
$(k+1)^q=sum k^i*C(q,i)$
可以$O(nq^2)$DP
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define MOD 998244353 4 #define M 1000010 5 int fac[M], inv[M], f[M]; 6 int v[M]; 7 int C[20][20]; 8 int main() { 9 int n, m, q; 10 scanf("%d%d%d", &n, &m, &q); 11 fac[0] = 1; 12 for(int i = 1; i <= n; ++ i) { 13 fac[i] = 1ll * fac[i - 1] * i % MOD; 14 } 15 inv[0] = inv[1] = 1; 16 for(int i = 2; i <= n; ++ i) { 17 inv[i] = 1ll * (MOD - MOD / i) * inv[MOD % i] % MOD; 18 } 19 for(int i = 0; i <= q; ++ i) v[i] = 1; 20 for(int i = 0; i <= 10; ++ i) C[i][0] = 1; 21 for(int i = 1; i <= 10; ++ i) { 22 for(int j = 1; j <= i; ++ j) { 23 C[i][j] = C[i - 1][j - 1] + C[i - 1][j]; 24 if(C[i][j] >= MOD) C[i][j] -= MOD; 25 } 26 } 27 int o = 0; 28 for(int i = m + 1; i <= n; ++ i) { 29 for(int j = q; j >= 0; -- j) { 30 for(int k = 0; k < j; ++ k) { 31 v[j] += 1ll * v[k] * C[j][k] % MOD; 32 if(v[j] >= MOD) v[j] -= MOD; 33 } 34 v[j] = 1ll * v[j] * (i - m) % MOD * inv[i] % MOD; 35 } 36 o = 1ll * o * (i - m) % MOD * inv[i] % MOD; 37 f[i] = (1ll * v[q] + o + 1ll * m * inv[i] % MOD) * i % MOD * inv[i - m] % MOD; 38 o += 1ll * f[i] * m % MOD * inv[i] % MOD; 39 if(o >= MOD) o -= MOD; 40 for(int j = 0; j <= q; ++ j) { 41 v[j] += 1ll * m * inv[i] % MOD; 42 if(v[j] >= MOD) v[j] -= MOD; 43 } 44 } 45 printf("%d ", f[n]); 46 }