luoguP4457 [BJOI2018]治疗之雨 概率期望 + 高斯消元
应该是最后一道紫色的概率了....然而颜色啥也代表不了....
首先看懂题意:
你现在有$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]治疗之雨 概率期望 + 高斯消元的更多相关文章
- [BZOJ5292][BJOI2018]治疗之雨(概率DP+高斯消元)
https://blog.csdn.net/xyz32768/article/details/83217209 不难找到DP方程与辅助DP方程,发现DP方程具有后效性,于是高斯消元即可. 但朴素消元显 ...
- BZOJ.3143.[HNOI2013]游走(概率 期望 高斯消元)
题目链接 参考 远航之曲 把走每条边的概率乘上分配的标号就是它的期望,所以我们肯定是把大的编号分配给走的概率最低的边. 我们只要计算出经过所有点的概率,就可以得出经过一条边(\(u->v\))的 ...
- [HNOI2011]XOR和路径 概率期望 高斯消元
题面 题解:因为异或不太好处理,,,因此按位来算,这样最后的答案就是每一位上的值乘对应的权值再求和.本着期望要倒退的原则,,,我们设$f[i]$表示从$i$到$n$,xor和为1的概率.那么观察$xo ...
- [HNOI2013] 游走 - 概率期望,高斯消元,贪心
假如我们知道了每条边经过的期望次数,则变成了一个显然的贪心.现在考虑如何求期望次数. 由于走到每个点后各向等概率,很显然一条边的期望次数可以与它的两个端点的期望次数,转化为求点的期望次数 考虑每个点对 ...
- 4.23 子串 AC自动机 概率期望 高斯消元
考虑40分. 设出状态 f[i]表示匹配到了i位还有多少期望长度能停止.可以发现这个状态有环 需要高斯消元. 提供一种比较简单的方法:由于期望的线性可加性 可以设状态f[i]表示由匹配到i到匹配到i+ ...
- BZOJ4820 SDOI2017硬币游戏(概率期望+高斯消元+kmp)
容易想到的做法是建出AC自动机,高斯消元.然而自动机上节点数量是nm的. 注意到我们要求的变量只有n个,考虑将其他不用求的节点合并为一个变量.这个变量即表示随机生成一个串,其不包含任何一个模板串的概率 ...
- UVA-10828 (概率期望+高斯消元)
题意: 给个有向图,每个节点等概率转移到它的后继节点,现在问一些节点的期望访问次数; 思路: 对于一个点v,Ev=Ea/d[a]+Eb/d[b]+Ec/d[c];a,b,c是v的前驱节点; 然后按这个 ...
- luoguP3232 [HNOI2013]游走 贪心 + 概率期望 + 高斯消元
首先,题目中的无向简单连通图代表着没有自环,重边... 总分的期望 = 每条边的期望之和...................每条边的期望又可以拆成$u \to v$的期望和$v \to u$的期望 ...
- 【BZOJ】3143: [Hnoi2013]游走 期望+高斯消元
[题意]给定n个点m条边的无向连通图,每条路径的代价是其编号大小,每个点等概率往周围走,要求给所有边编号,使得从1到n的期望总分最小(求该总分).n<=500. [算法]期望+高斯消元 [题解] ...
随机推荐
- JSDom
什么是Dom? 1.简介 文档对象模型(Document Object Model,简称DOM),是W3C组织推荐的处理可扩展标志语言的标准编程接口.Document Object Model的历史可 ...
- NYOJ 756 重建二叉树 (二叉树)
题目链接 描述 题目很简单,给你一棵二叉树的后序和中序序列,求出它的前序序列(So easy!). 输入 输入有多组数据(少于100组),以文件结尾结束.每组数据仅一行,包括两个字符串,中间用空格隔开 ...
- 基于canvas实现的fontawesome动态图标
由于还没有全部实现,实现了一些demo,demo地址在 https://github.com/jiangzhenfei/canvas-fontawesome 实现了动态loading 实现动态电池充电 ...
- Thinkphp的SQL查询方式
一.普通查询方式 a.字符串$arr=$m->where("sex=0 and username='gege'")->find();b.数组$data['sex']=0 ...
- linux下C语言实现多线程通信—环形缓冲区,可用于生产者(producer)/消费者(consumer)【转】
转自:http://blog.chinaunix.net/uid-28458801-id-4262445.html 操作系统:ubuntu10.04 前言: 在嵌入式开发中,只要是带操作系统的 ...
- Eclipse java项目转换为web项目
1.打开.project文件,并修改文件, 修改如下: 找到:<natures> </natures>代码段,在代码段中加入如下内容并保存: <nature>org ...
- Tomcat: Connector中HTTP与AJP差别与整合
apache tomcat 整合(ajp proxy, http proxy) 1.软件: apache: httpd-2.2.17-win32-x86-openssl-0.9.8o.msi tomc ...
- plsPlugin
init: 监控目录变化(增删) 监控jar变化,load
- python基础(8)--迭代器、生成器、装饰器
1.迭代器 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退,不过这也没什么,因为人们很少在迭代途中往后退.另外,迭代器的一大优 ...
- git的一些配置
git使用socks代理加速 原来git可以配置socks代理的,真好,从github上clone了opencv的代码,基本上是满速了. 首先需要配置shadowsocks,然后通过GUI客户端(或命 ...