zoukankan      html  css  js  c++  java
  • 抽鬼牌(poker)

    题目描述

    小海喜欢和小鸟玩抽鬼牌,规则如下:小鸟每次有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 }
  • 相关阅读:
    Python中判断字典的键或值在不在字典中
    Python中字符串,列表,元组三者之间相互转换
    mysql /*! */
    【kubernetes入门学习】使用minikube创建k8s本地单节点集群
    Java中发生内存泄漏的常见场景
    python的list()列表数据类型的方法详解
    python的str()字符串类型的方法详解
    python的运算符
    python基础之while语句continue以及break --语法以及案例
    python的if条件语句的语法和案例
  • 原文地址:https://www.cnblogs.com/iamqzh233/p/9435377.html
Copyright © 2011-2022 走看看