首页 > 其他分享 >【洛谷】P4457 [BJOI2018]治疗之雨(期望+高斯消元)

【洛谷】P4457 [BJOI2018]治疗之雨(期望+高斯消元)

时间:2023-03-13 20:35:28浏览次数:60  
标签:BJOI2018 frac P4457 int res leq ldots 高斯消 mod

原题链接

题意

初始时玩家有 \(p\) 滴血,满血 \(n\) 滴,每个回合会进行如下操作:

  • 若当前还没有满血,则以 \(\frac{1}{m+1}\) 的概率增加一滴血;

  • \(k\) 次判定,每次以 \(\frac{1}{m+1}\) 的概率扣除一滴血,当血量减少为 \(0\) 时游戏结束。

求玩家能存活的期望回合数。

\(1 \leq p \leq n \leq 1500\) ,\(0 \leq m, k \leq 10^9\)。

思路

设一个回合扣除 \(i\) 滴血的概率为 \(P_i(i \leq k)\),由数学选修三的知识可知,这其实是一个伯努利试验的模型,可以得到表达式:

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

由于:

\[\dfrac{P_i}{P_{i-1}}=\dfrac{\binom{n}{i} (\frac{1}{{m+1}})^i (\frac{m}{{m+1}})^{n-i}}{\binom{n}{i-1} (\frac{1}{{m+1}})^{i-1} (\frac{m}{{m+1}})^{n-i+1}} \]

可以得到递推式:

\[P_i=P_{i-1} \times \frac{1}{m} \times \frac{k-i+1}{i} \]

由于一个回合最多一次将满血全部扣完,所以这部分可以 \(O(n)\) 预处理得到。

设 \(f_i\) 为有 \(i\) 滴血的期望存活回合数,当 \(i\in [1,n-1]\) 时,简单分类讨论不难得到表达式:

\[f_i=\sum_{j=1}^{i}f_j (\frac{1}{m+1} P_{i+1-j}+\frac{m}{m+1}P_{i-j})+\frac{1}{m+1}P_0 f_{i+1}+1 \]

其中当 \(i=n\) 时,由于此时不能再加血,所以此时的表达式为:

\[f_n=\sum_{j=1}^{n} P_{n-j} f_j+1 \]

这里一共有 \(n\) 个方程以及 \(n\) 个位置数,高斯消元可以得出答案。然而直接消元的复杂度为 \(O(n^3)\),需要考虑优化。

列出方程组,当 \(a_{i,j}=1\) 时表示这一项的系数不为 \(0\),反之则表示这一项不存在,可以得到:

\[\begin{bmatrix} 1& 1& 0& 0& 0& \ldots 1&\\ 1& 1& 1& 0& 0& \ldots 1&\\ 1& 1& 1& 1& 0& \ldots 1&\\ \ldots \\ 1& 1& 1& 1& 1& \ldots 1&\\ \end{bmatrix}\]

发现这个方程的形式很特殊,每次往下消元的时候只需要带入两个值,消去这一行第一个非空的系数,最终得到的形式是这样的:

\[\begin{bmatrix} 1& 1& 0& 0& 0& \ldots 1&\\ 0& 1& 1& 0& 0& \ldots 1&\\ 0& 0& 1& 1& 0& \ldots 1&\\ \ldots \\ 0& 0& 0& 0& 1& \ldots 1&\\ \end{bmatrix}\]

最后一行就是 \(x=A\) 的形式了,那么只需要向上回带就可以解出所有的未知数,最终的复杂度为 \(O(n^2)\)。

最后,还需要特判一下 \(k=0\) 和 \(m=0\) 的情况。

code:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define LL long long
const int N=2023,mod=1e9+7;
int n,p,m,k;LL P[N],a[N][N];//初始p滴血,满血n滴,1/(m+1)概率加血,1/(m+1)概率扣血->k次 
int mul(int a,int b){int res=1;while(b) ((b&1)&&(res=1ll*res*a%mod,0)),a=1ll*a*a%mod,b>>=1;return res;}
void Gauss()
{
	for(int i=1;i<=n;i++)
    {
    	LL inv=mul(a[i][i],mod-2);a[i][i]=1;a[i][n+1]=a[i][n+1]*inv%mod;
    	if(i!=n) a[i][i+1]=a[i][i+1]*inv%mod;
    	for(int j=i+1;j<=n;j++)
    	{
    		LL mult=a[j][i];a[j][i]=0;a[j][i+1]=(a[j][i+1]-mult*a[i][i+1]%mod+mod)%mod;
    		a[j][n+1]=(a[j][n+1]-mult*a[i][n+1]%mod+mod)%mod;
		}
	}
	for(int i=n;i>1;i--) a[i-1][n+1]=(a[i-1][n+1]-a[i-1][i]*a[i][n+1]%mod+mod)%mod,a[i-1][i]=0;
}
void solve()
{
	scanf("%d%d%d%d",&n,&p,&m,&k);
	if(k==0) return puts("-1"),void();
	if(m==0)
	{
		if(k==1) return puts("-1"),void();int res=0;
		while(p>0){if(p<n) p++;p-=k;res++;} return printf("%d\n",res),void();
	}
	for(int i=1;i<N;i++) P[i]=0;
	LL invm=mul(m,mod-2),invm1=mul(m+1,mod-2);P[0]=mul(1ll*m*mul(m+1,mod-2)%mod,k);
	for(int i=1;i<=min(n+1,k);i++) P[i]=P[i-1]*invm%mod*mul(i,mod-2)%mod*(k-i+1)%mod;
	for(int i=1;i<=n;i++) for(int j=1;j<=n+1;j++) a[i][j]=0;
	for(int i=1;i<n;i++) for(int j=1;j<=i;j++) a[i][j]=(P[i-j]*m+P[i-j+1])%mod*invm1%mod;
	for(int i=1;i<n;i++) a[i][i+1]=P[0]*invm1%mod;
	for(int i=1;i<n;i++) a[i][i]=(a[i][i]-1+mod)%mod;
	for(int i=1;i<=n;i++) a[i][n+1]=mod-1;
	for(int i=1;i<=n;i++) a[n][i]=P[n-i];a[n][n]=(a[n][n]-1+mod)%mod;
	Gauss();printf("%lld\n",(a[p][n+1]%mod+mod)%mod);
}
int main()
{
//	freopen("in.txt","r",stdin);
	int T;scanf("%d",&T);while(T--) solve();
	return 0;
} 

标签:BJOI2018,frac,P4457,int,res,leq,ldots,高斯消,mod
From: https://www.cnblogs.com/ListenSnow/p/17212763.html

相关文章

  • 【YBT2023寒假Day3 A】千与千寻(期望DP)(高斯消元)
    千与千寻题目链接:YBT2023寒假Day3A题目大意一个n*m的平面,你要从(0,0)走到(x,y),你等概率的向上或向右走,然后当你走到(n-1,i)再往右走,就是(0,i),走到(i,m-1)再......
  • 高斯消元法
    高斯消元法心情不好,来写博客...思想一种通过消元求解线性方程组的方法,时间复杂度为\(n^3\)和普通的消元法无二,选定一个自变量为主元,将一行的主元系数化为一,再通过乘......
  • 高斯消元
    简述高斯消元法(Gauss-Jordanelimination)是求解线性方程组的经典算法,它在当代数学中有着重要的地位和价值,是线性代数课程教学的重要组成部分。高斯消元法除了用于线性方......
  • C++ 数学与算法系列之高斯消元法求解线性方程组
    1.前言什么是消元法?消元法是指将多个方程式组成的方程组中的若干个变量通过有限次地变换,消去方程式中的变量,通过简化方程式,从而获取结果的一种解题方法。消元法主要有代......
  • 数值分析·学习 | 解线性方程组的直接方法(高斯消去法以及LU求解)matlab实现
    ​ 目录一、前言:二、算法描述:三、实现代码:1、高斯消去法:2、高斯消去法-列主元消去法:3、LU分解:4、求逆矩阵:四、总结:一、前言:个人学习内容分享二、算法描述:1......
  • 高斯消元+组合数+卡特兰数
    高斯消元+组合数+卡特兰数高斯消元\(O(n^3)\)的线性时间内求解n元线性方程组\[\\\begin{cases}\a_{11}x_1+a_{12}x_2+...+a_{1n}x_n=b_1\\\a_{21}x_1+a_{22}x_2+.......
  • 算法学习笔记(39)——高斯消元
    高斯消元高斯消元高斯消元解线性方程组高斯消元解异或线性方程组高斯消元解线性方程组通过初等行变换把增广矩阵化为阶梯型矩阵,并回代得到方程的解适用于求解......
  • 高斯消元与线性基
    高斯消元与线性基Guass—约旦消元消元算法简介:这是求解线性方程组(也就是M个N元一次方程组)的方法思想:我们可以把方程组看作一个系数矩阵例如:\[\left\{\begin{aligned......
  • 高斯消元&高斯约旦消元
    高斯消元就是上三角,然后再回代。高斯约旦消元就是消的时候直接变成对角线了,你选取当前主元,然后把其他的都消去这个元。一般来说就写后者。注意二者都要特判自由元,但常数......
  • 高斯消元
    0x00背景高斯消元是求线性方程组的标准方法,原理和代码都不难0x01基本操作一个线性方程组有\(m\)个一次方程,\(n\)个变量,把所有系数都写成一个\(m\)行\(n\)列的矩阵,......