[深海少女与胖头鱼]

深海少女与胖头鱼

题目大意

\(n\)个带盾的鱼和\(m\)个不带盾的鱼,求将他们全部打死的期望次数(其中打到带盾的鱼会让它的盾消失,但是又会让其他所有鱼带上护盾)

做法

考虑两种情况:打到带盾的鱼和不带盾的鱼,我们令\(f(n,m)\)表示打死\(n\)个带盾的和\(m\)个不带盾的期望值

情况1:打到了带盾的,概率是\(\frac{n}{n+m}\),那么攻击完这一下之后将会面对的情况就是\(n+m-1\)个带盾的和\(1\)个不带盾的

情况2:打到了不带盾的,概率是\(\frac{m}{n+m}\),那么攻击完这一下之后将会面对的情况是\(n\)个带盾的和\(m-1\)个不带盾的

综上可以推出公式$$f(n,m)=\frac{n}{n+m}×f(n+m-1,1)+\frac{m}{n+m}×f(n,m-1)+1$$

根据上式可以发现,出现了\(m-1\),所以只适用于\(m≥1\)的情况,于是我们考虑\(m=0\)时,由于只能打带盾的故:\(f(n,0)=f(n-1,1)+1\),这个\(f(n-1,1)\)套入刚才的公式联立就可以得到

\[\left\{\begin{matrix} f(n-1,1)=\frac{n-1}{n}×f(n,1)+\frac{1}{n}×f(n,0)+1 ①\\ f(n,0)=f(n-1,1)+1 ② \end{matrix}\right.\]

将②代入①得到:\(f(n,1)=f(n-1,1)+n+2\)递推式的话可以相加

\(f(n,1)=f(n-1,1)+n+2\)
\(f(n-1,1)=f(n-2,1)+(n-1)+2\)
\(f(n-2,1)=f(n-3,1)+(n-2)+2\)
.
.
.
\(f(1,1)=f(0,1)+1+2\)

将上面的式子相加会得到\(f(n,1)=f(0,1)+2n+\sum_{i=1}^{n}i\)其中\(f(0,1)=1\)

整理得\(f(n,1)=\frac{n^2+5n+2}{2}\)定义一个函数\(calc(x)=\frac{x^2+5x+2}{2}\)

综上就推出了对\(m\)所有的情况,

\[f(n,m)=\left\{\begin{matrix} f(n,0)=f(n-1,1)+1=calc(n-1)+1 \qquad (m=0)\\ f(n,1)=calc(n) \qquad (m=1) \\ f(n,m)=\frac{n}{n+m}×calc(n+m-1)+\frac{m}{n+m}×f(n,m-1)+1 \end{matrix}\right.\]

说明

因为程序中设计到分数,比如\(\frac{n}{n+m}\)它等效于\(n×(n+m)^{-1}\)其实我们要求\((n+m)\)在模\(p\)意义下的逆元,由于题目中给的998244353是质数,则有\(a^{p-1}≡1~(mod~p)\),所以\(a\)在模\(p\)下的逆元是\(a^{p-2}~mod~p\)

洛谷P6858

#include <cstdio>
#include <iostream>
typedef long long LL;
using namespace std;
const int mod = 998244353;
LL n,m;

LL inv(LL a)
{
	LL res = 1;
	a %= mod;
	LL b = mod - 2;
	while(b)
	{
		if(b & 1)
			res = res * a % mod;
		a = a * a % mod;
		b >>= 1;
 	}
 	return res;
}

LL quickmul(LL a,LL b)
{
	LL res = 0;
	while(b)
	{
		if(b & 1)
			res += a, res %= mod;
		a = (a + a) % mod;
		b >>= 1;
	}
	return res;
}

LL calc(LL x)
{
	x %= mod;
	LL res = x * (x+5) + 2;
	res >>= 1;
	return res % mod;
}

LL f(LL n,LL m)
{
	if(!m) return calc(n-1)+1;
	else if(m == 1) return calc(n);
	else {
		LL Inv = inv(n+m);
		return 1 + (quickmul(n,Inv)*calc(n+m-1)%mod) + (quickmul(m,Inv)*f(n,m-1)%mod);
	}
}

int main()
{
	scanf("%lld%lld",&n,&m);
//	printf("%lld",quickmul(n,m));
	printf("%lld",f(n,m) % mod);
	return 0;
}
posted @ 2024-07-25 11:37  -凨-  阅读(41)  评论(1)    收藏  举报