应该是最后一道紫色的概率了....然而颜色啥也代表不了....

首先看懂题意:

你现在有$p$点体力,你的体力上限为$n$

在一轮中,

1.如果你的体力没有满,你有$\frac{1}{m + 1}$的几率回复一点体力

2.紧接着有$k$轮攻击,每轮攻击都有$\frac{1}{m + 1}$的几率使你掉一点体力

如果一轮后,你的体力$ \leq 0$,那么游戏结束

询问游戏结束的期望轮数

看懂题应该就懂了什么吧....

设状态$f[i]$表示生命值为$i$游戏结束的期望轮数

那么

$$f[i] = \begin{cases}
& 0\;\;(i = 0)\\
& 1 + \sum\limits_{j = 1}^i f[j] * P[i - j]\;\;(i = n)\\
& 1 + \sum\limits_{j = 1}^i f[j] * (\frac{P[i - j + 1]}{m + 1} + \frac{m * P[i - j]}{m + 1}) + f[i + 1]*\frac{P[0]}{m + 1} \;\;(else)
\end{cases}$$

其中,$P[i]$表示在一轮攻击中受到$i$点攻击的概率

($f[0]$结束游戏,因此不能向别的状态转移)

考虑怎么求$P[i]$

由于确定了$i$种要攻击,其余的不攻击,那么一种攻击方式的概率为$(\frac{1}{m + 1})^i * (\frac{m}{m + 1})^{k - i}$

对于攻击$i$次而言,总共有$C(k, i)$种攻击方式

因此$P[i] = C(k, i) *(\frac{1}{m + 1})^i * (\frac{m}{m + 1})^{k - i} $

直接$O(n^2)$暴力全部求出来...

那么,有了$P[i]$后,高斯消元的复杂度过高

但是,注意到方程中$0$的数量非常的多,因此在消元的时候把$0$项跳过

酱紫,复杂度就到$O($玄学$)$了,仔细优化一下就$O(n^2)$了,具体看代码吧....

注:记得判无解

注2:不知道为什么$P[]$数组莫名的要多预处理一些.....

注(注2):仿佛是$n = 0$的时候挂了.....出题人有猫病啊.....

复杂度$O(Tn^2)$,没怎么卡常

#include <cstdio>
using namespace std; extern inline char gc() {
static char RR[], *S = RR + , *T = RR + ;
if(S == T) fread(RR, , , stdin), S = RR;
return *S ++;
}
inline int read() {
int p = , w = ; char c = gc();
while(c > '' || c < '') { if(c == '-') w = -; c = gc(); }
while(c >= '' && c <= '') p = p * + c - '', c = gc();
return p * w;
} #define sid 1600
#define eid 200050
#define ri register int
const int mod = ; int n, p, m, k;
int inv[eid], P[sid], f[sid][sid]; void Init_Inv() {
inv[] = inv[] = ;
for(ri i = ; i <= ; i ++)
inv[i] = 1ll * (mod - mod / i) * inv[mod % i] % mod;
for(ri i = ; i <= ; i ++)
inv[i] = 1ll * inv[i - ] * inv[i] % mod;
} int fp(int a, int k) {
int ret = ;
for( ; k; k >>= , a = 1ll * a * a % mod)
if(k & ) ret = 1ll * ret * a % mod;
return ret;
} void Init_P() {
int invm = fp(fp(m + , mod - ), k);
for(ri i = ; i <= n + ; i ++) {
if(i > k) { P[i] = ; continue; }
int C = ;
for(ri j = k - i + ; j <= k; j ++) C = 1ll * C * j % mod;
C = 1ll * C * inv[i] % mod;
P[i] = 1ll * C * fp(m, k - i) % mod * invm % mod;
}
} void Init_Guass() {
int m11 = fp(m + , mod - );
int mm1 = 1ll * m * m11 % mod;
for(ri i = ; i <= n + ; i ++)
for(ri j = ; j <= n + ; j ++)
f[i][j] = ;
for(ri i = ; i < n; i ++) {
f[i][i] = ; f[i][n + ] = ;
f[i][i + ] = (mod - 1ll * P[] * m11 % mod);
for(ri j = ; j <= i; j ++) {
f[i][j] = (f[i][j] - 1ll * m11 * P[i - j + ] % mod + mod) % mod;
f[i][j] = (f[i][j] - 1ll * mm1 * P[i - j] % mod + mod) % mod;
}
}
f[n][n] = ; f[n][n + ] = ;
for(ri i = ; i <= n; i ++) f[n][i] = (f[n][i] - P[n - i] + mod) % mod;
} void Guass() {
for(ri i = ; i <= n; i ++) {
int inv = fp(f[i][i], mod - );
for(ri j = i + ; j <= n; j ++) {
int t = 1ll * f[j][i] * inv % mod;
for(ri k = i; k <= i + ; k ++)
f[j][k] = (f[j][k] - 1ll * f[i][k] * t % mod + mod) % mod;
f[j][n + ] = (f[j][n + ] - 1ll * f[i][n + ] * t % mod + mod) % mod;
}
}
for(ri i = n; i >= ; i --) {
f[i][n + ] = 1ll * f[i][n + ] * fp(f[i][i], mod - ) % mod;
f[i - ][n + ] = (f[i - ][n + ] - 1ll * f[i - ][i] * f[i][n + ] % mod + mod) % mod;
}
} int main() {
int Tt = read();
Init_Inv();
while(Tt --) {
n = read(); p = read(); m = read(); k = read();
if(k == ) { printf("-1\n"); continue; }
if(m == && k == ) { printf("-1\n"); continue; }
Init_P(); Init_Guass(); Guass();
     int ans = f[p][n + ];
printf("%d\n", ans);
}
return ;
}

luoguP4457 [BJOI2018]治疗之雨 概率期望 + 高斯消元的更多相关文章

  1. [BZOJ5292][BJOI2018]治疗之雨(概率DP+高斯消元)

    https://blog.csdn.net/xyz32768/article/details/83217209 不难找到DP方程与辅助DP方程,发现DP方程具有后效性,于是高斯消元即可. 但朴素消元显 ...

  2. BZOJ.3143.[HNOI2013]游走(概率 期望 高斯消元)

    题目链接 参考 远航之曲 把走每条边的概率乘上分配的标号就是它的期望,所以我们肯定是把大的编号分配给走的概率最低的边. 我们只要计算出经过所有点的概率,就可以得出经过一条边(\(u->v\))的 ...

  3. [HNOI2011]XOR和路径 概率期望 高斯消元

    题面 题解:因为异或不太好处理,,,因此按位来算,这样最后的答案就是每一位上的值乘对应的权值再求和.本着期望要倒退的原则,,,我们设$f[i]$表示从$i$到$n$,xor和为1的概率.那么观察$xo ...

  4. [HNOI2013] 游走 - 概率期望,高斯消元,贪心

    假如我们知道了每条边经过的期望次数,则变成了一个显然的贪心.现在考虑如何求期望次数. 由于走到每个点后各向等概率,很显然一条边的期望次数可以与它的两个端点的期望次数,转化为求点的期望次数 考虑每个点对 ...

  5. 4.23 子串 AC自动机 概率期望 高斯消元

    考虑40分. 设出状态 f[i]表示匹配到了i位还有多少期望长度能停止.可以发现这个状态有环 需要高斯消元. 提供一种比较简单的方法:由于期望的线性可加性 可以设状态f[i]表示由匹配到i到匹配到i+ ...

  6. BZOJ4820 SDOI2017硬币游戏(概率期望+高斯消元+kmp)

    容易想到的做法是建出AC自动机,高斯消元.然而自动机上节点数量是nm的. 注意到我们要求的变量只有n个,考虑将其他不用求的节点合并为一个变量.这个变量即表示随机生成一个串,其不包含任何一个模板串的概率 ...

  7. UVA-10828 (概率期望+高斯消元)

    题意: 给个有向图,每个节点等概率转移到它的后继节点,现在问一些节点的期望访问次数; 思路: 对于一个点v,Ev=Ea/d[a]+Eb/d[b]+Ec/d[c];a,b,c是v的前驱节点; 然后按这个 ...

  8. luoguP3232 [HNOI2013]游走 贪心 + 概率期望 + 高斯消元

    首先,题目中的无向简单连通图代表着没有自环,重边... 总分的期望 = 每条边的期望之和...................每条边的期望又可以拆成$u \to v$的期望和$v \to u$的期望 ...

  9. 【BZOJ】3143: [Hnoi2013]游走 期望+高斯消元

    [题意]给定n个点m条边的无向连通图,每条路径的代价是其编号大小,每个点等概率往周围走,要求给所有边编号,使得从1到n的期望总分最小(求该总分).n<=500. [算法]期望+高斯消元 [题解] ...

随机推荐

  1. JavaScript三种绑定事件的方式

    JavaScript三种绑定事件的方式: 1. <div id="btn" onclick="clickone()"></div> // ...

  2. C基础 time.h 简单思路扩展

    前言 - time 简单需求 时间业务相关代码. 基本属于框架的最底层. 涉及的变动都很小. 以前参与游戏研发时候, 这方面需求不少, 各种被策划花式吊打. 转行开发互联网服务之后很少遇到这方面需求. ...

  3. QWT编译、配置、使用(Qt Creator)

    环境: Win7 32 bit / Qt Creator 3.3.1 / Qt 5.4.1 (msvc2013_opengl, 32 bit) / QWT 6.1.2 QWT, Qt Widgets ...

  4. 8.Python3标准库--数据持久存储与交换

    ''' 持久存储数据以便长期使用包括两个方面:在对象的内存中表示和存储格式之间来回转换数据,以及处理转换后数据的存储区. 标准库包含很多模块可以处理不同情况下的这两个方面 有两个模块可以将对象转换为一 ...

  5. WDCP各种停止重启命令

    service wdapache start|stop|restart    wdcp后台 启动|停止|重起service nginxd start|stop|restart        nginx ...

  6. leetcode 之Longest Consecutive Sequence(六)

    这题要仔细体会下哈希表的用法,要注意的是数组本身是无序的,因此需要向左右进行扩张. 另外这个思路可以进行聚类,把连续的标记为一类. int longestConsecutive(const vecto ...

  7. Selenium_Grid

    Selenium Grid 工作原理 Grid是一种分布式测试工具,整个结果由一个hub主节点和若干个node代理节点组成. hub用来管理各个代理节点的注册和状态信息,并且接收远程客户端代码请求调用 ...

  8. DedeCms当前位置导航去掉最后的分隔符>

    DedeCms的当前位置导航调用标签{dede:field name=’position’ /},在栏目页里调用的当前位置导航,最后会出现分割符号“>”,如:主页 > DedeCms 模板 ...

  9. 洛谷 P2369 EXCEEDED WARNING A 题解

    题目传送门 直接用sort排序最后输出即可.但是数组要使用short int 类型.否则会超内存. #include<bits/stdc++.h> using namespace std; ...

  10. print、println的区别

    System.out.print("a");——后面没有换行符 System.out.println("b");——后面有换行符 换行符:\r和\n以及\r\n ...