正题

题目链接:https://www.luogu.com.cn/problem/P4457


题目大意

开始一个人最大生命值为\(n\),剩余\(hp\)点生命,然后每个时刻如果生命值没有满那么有\(\frac{1}{m+1}\)的概率回复一点生命,然后敌人攻击\(k\)次,每次有\(\frac{1}{m+1}\)概率造成一点伤害。

求期望多少次后生命值降到\(0\)或以下。

\(1\leq T\leq 100,1\leq n\leq 1500,1\leq m,k\leq 10^9\)


解题思路

\(dp\)方程还是很好推的,设\(p_i\)表示在敌人攻击时受到\(i\)点伤害的概率,那么就是

\[p_i=(\frac{1}{m+1})^i(\frac{m}{m+1})^{k-i}\binom{k}{i}
\]

的概率,这个\(i\)只需要计算到\(n\)就好了。

然后设\(f_i\)表示剩余\(i\)点生命时期望还需要打多久

然后枚举一个\(j\)表示本回合受到的伤害,分成回复了生命或者没有回复生命两种情况,方程就是

\[f_i=\frac{1}{m+1}(\sum_{j=0}^{i}p_jf_{i-j+1})+\frac{m}{m+1}(\sum_{j=0}^{i-1}p_jf_{i-j}+1)
\]

当然\(f_n\)需要特殊处理

\[f_n=\sum_{i=0}^np_if_{n-i}+1
\]

发现这个方程是有前有后的环状转移,但是暴力高斯消元\(O(n^3)\)的时间复杂度接受不了。

不难发现的是我们现在的方程矩阵其实就是一个下三角矩阵再往右扩一列。我们可以先\(O(n^2)\)把这个下三角消成对角线然后第\(i\)列就只有\(i\)和\(i+1\)两个系数了,反过来再消一次就好了。

时间复杂度\(O(Tn^2)\)


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=1600,P=1e9+7;
ll T,n,hp,m,k,a[N][N],b[N];
ll inv[N],p[N];
ll power(ll x,ll b){
ll ans=1;
while(b){
if(b&1)ans=ans*x%P;
x=x*x%P;b>>=1;
}
return ans;
}
ll C(ll n,ll m){
ll ans=1;
for(ll i=n-m+1;i<=n;i++)ans=ans*i%P;
return ans*inv[m]%P;
}
signed main()
{
inv[1]=1;
for(ll i=2;i<N;i++)
inv[i]=P-(P/i)*inv[P%i]%P;
inv[0]=1;
for(ll i=1;i<N;i++)
inv[i]=inv[i-1]*inv[i]%P;
scanf("%lld",&T);
while(T--){
scanf("%lld%lld%lld%lld",&n,&hp,&m,&k);
ll invm=power(m+1,P-2);
if(!k||k==1&&!m){puts("-1");continue;}
else if(!m){
ll ans=0;
while(hp>0){if(hp<n)hp++;hp-=k;ans++;}
printf("%lld\n",ans);continue;
}
ll tmp=power(invm,k);
for(ll i=0;i<=min(k,n);i++)
p[i]=tmp*power(m,k-i)%P*C(k,i)%P;
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
for(ll i=0;i<=min(k,n-1);i++)
a[n][n-i]=P-p[i];
a[n][n]++;b[n]++;
for(ll i=1;i<n;i++){
a[i][i]=1;b[i]=1;
for(ll j=0;j<=min(k,i-1);j++)
(a[i][i-j]+=P-invm*m%P*p[j]%P)%=P;
for(ll j=0;j<=min(k,i);j++)
(a[i][i-j+1]+=P-invm*p[j]%P)%=P;
}
for(ll i=1;i<=n;i++){
ll inv=power(a[i][i],P-2);
a[i][i]=1;b[i]=b[i]*inv%P;
a[i][i+1]=a[i][i+1]*inv%P;
for(ll j=i+1;j<=n;j++){
ll rate=P-a[j][i];a[j][i]=0;
(a[j][i+1]+=a[i][i+1]*rate)%=P;
(b[j]+=b[i]*rate)%=P;
}
}
for(ll i=n-1;i>=1;i--){
ll rate=P-a[i][i+1];
b[i]=(b[i]+rate*b[i+1])%P;
}
printf("%lld\n",(b[hp]+P)%P);
}
return 0;
}

P4457-[BJOI2018]治疗之雨【期望dp,高斯消元】的更多相关文章

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

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

  2. BZOJ_3143_[Hnoi2013]游走_期望DP+高斯消元

    BZOJ_3143_[Hnoi2013]游走_期望DP+高斯消元 题意: 一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机 ...

  3. HDU 2262 Where is the canteen 期望dp+高斯消元

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2262 Where is the canteen Time Limit: 10000/5000 MS ...

  4. hdu4418 Time travel 【期望dp + 高斯消元】

    题目链接 BZOJ4418 题解 题意:从一个序列上某一点开始沿一个方向走,走到头返回,每次走的步长各有概率,问走到一点的期望步数,或者无解 我们先将序列倍长形成循环序列,\(n = (N - 1) ...

  5. 【noi2019集训题1】 脑部进食 期望dp+高斯消元

    题目大意:有n个点,m条有向边,每条边上有一个小写字母. 有一个人从1号点开始在这个图上随机游走,游走过程中他会按顺序记录下走过的边上的字符. 如果在某个时刻,他记录下的字符串中,存在一个子序列和S2 ...

  6. LightOJ 1151 Snakes and Ladders 期望dp+高斯消元

    题目传送门 题目大意:10*10的地图,不过可以直接看成1*100的,从1出发,要到达100,每次走的步数用一个大小为6的骰子决定.地图上有很多个通道 A可以直接到B,不过A和B大小不确定   而且 ...

  7. ZJUT 1423 地下迷宫(期望DP&高斯消元)

    地下迷宫 Time Limit:1000MS  Memory Limit:32768K Description: 由于山体滑坡,DK被困在了地下蜘蛛王国迷宫.为了抢在DH之前来到TFT,DK必须尽快走 ...

  8. Codeforces.24D.Broken robot(期望DP 高斯消元)

    题目链接 可能这儿的会更易懂一些(表示不想再多写了). 令\(f[i][j]\)表示从\((i,j)\)到达最后一行的期望步数.那么有\(f[n][j]=0\). 若\(m=1\),答案是\(2(n- ...

  9. HDU4418 Time travel(期望dp 高斯消元)

    题意 题目链接 Sol mdzz这题真的太恶心了.. 首先不难看出这就是个高斯消元解方程的板子题 \(f[x] = \sum_{i = 1}^n f[to(x + i)] * p[i] + ave\) ...

随机推荐

  1. qt 中回调函数的实现

    在QT中回调函数主要可以实现多态性,通过回调函数可以动态处理一些操作.在多线程中,当同时需要处理多个事务的时候,显然你会去创建多个线程类然后实例化,这显然会增加开发工作,当我们在线程类中加入一个回调函 ...

  2. Qt 中事件与处理

    一.事件与处理程序在运算过程中发生的一些事情:鼠标单击.键盘的按下...这些的事件的监控与处理在Qt中不是以信号的方式处理的.当这些事件发生时会调用QObject类中的功能函数(虚函数),所有的控件类 ...

  3. C++字符串【string】和【char []】操作全攻略

    异想之旅:本人博客完全手敲,绝对非搬运,全网不可能有重复:本人无团队,仅为技术爱好者进行分享,所有内容不牵扯广告.本人所有文章发布平台为CSDN.博客园.简书和开源中国,后期可能会有个人博客,除此之外 ...

  4. 项目版本管理Git使用详细教程

    前言 记得刚开始做项目开发的时候都是一个人完成一个项目,单打独斗的开发,也不知道什么是团队开发,没有这个概念,随着工作后来知道公司里项目都是团队开发,这个时候这么多人怎么开发一个项目呢,难道用u盘拷贝 ...

  5. MySQL-SQL基础

    mysql> use test; Database changed mysql> create table emp(ename varchar(10),hirdate date,sal d ...

  6. Android Parsing between JSON and Kotlin Object with Google Gson Library

    Parsing between JSON and Kotlin Object with Google Gson Library dependencies { ... implementation 'c ...

  7. vue js 手写 正则判断 手机号码 和 密码

    const phoneOrEmails = /^1[3|4|5|6|7|8|9][0-9]\d{8}$/             if(this.ruleForms.phoneOrEmail  ==  ...

  8. 2021 年 9 月 TIOBE 指数 C# 增长突破 1.2%

    TIOBE 编程社区指数是编程语言流行程度的指标.该指数每月更新一次.评级基于全球熟练工程师.课程和第三方供应商的数量.谷歌.必应.雅虎.维基百科.亚马逊.YouTube 和百度等流行搜索引擎用于计算 ...

  9. Linux常用命令 - rm命令详解

    21篇测试必备的Linux常用命令,每天敲一篇,每次敲三遍,每月一循环,全都可记住!! https://www.cnblogs.com/poloyy/category/1672457.html 删除/ ...

  10. DHCP的原理和配置

    前言 在大型企业网络中,会有大量的主机或设备需要获取IP地址等网络参数.如果采用手工配置,工作量大且不好管理,如果有用户擅自修改网络参数,还有可能会造成 IP地址冲突等问题.使用动态主机配置协议DHC ...