正题

题目链接: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. 如果被问到 HTTP 协议,你真的能讲清楚吗?

    前段时间,在和许久未见的老同学聊天时,突然被问到 http 协议到底是什么?脑海里面第一时间想起来的就是 request 请求.response 响应之类的词汇,但是这样讲他真的能知道是什么吗?我反问 ...

  2. C#基础知识---扩展方法

    一.简介 扩展方法为现有的类型(.Net类型或者自定义类型)扩展应该附加到该类型中的方法. 二.基本原则 定义一个非嵌套.非泛型的静态类 扩展方法是静态的 扩展方法至少要有一个参数,该参数类型是要扩展 ...

  3. Spring详解(五)------面向切面编程

    .AOP 什么? AOP(Aspect Oriented Programming),通常称为面向切面编程.它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的 ...

  4. 栈(Stack)

    特点: 栈最大的特点就是后进先出(LIFO).对于栈中的数据来说,所有操作都是在栈的顶部完成的,只可以查看栈顶部的元素,只能够向栈的顶部压入数据,也只能从栈的顶部弹出数据. 实现: 利用一个单链表来实 ...

  5. MyBatis like报错

    错误的likeSQL语句是这么写的 select * from student name like '%#{name}%' 下面是错误信息 Parameter index out of range ( ...

  6. NIO中的File

    package nio; import java.io.IOException; import java.nio.charset.Charset; import java.nio.file.Files ...

  7. Java程序设计学习笔记(二)

    --正则表达式    正则表达式         ^ 匹配的开始         $ 匹配的结束         [] 表示匹配任意一个字符             [asdasd]          ...

  8. Java 大数加法HdAcm1002

    1 import java.util.Scanner; 2 3 4 public class Main { 5 public static void main(String[] args) { 6 S ...

  9. tree命令出现乱码

    alias tree='tree --charset ASCII'就可以了

  10. 用C++实现的Eratosthenes筛法程序

    运行示例 只输出素数总数的运行示例 PS H:\Read\num\x64\Release> .\esieve.exe Eratosthenes sieve: a method to find o ...