题意
传送门 P6858 深海少女与胖头鱼
题解
设
A
(
n
,
m
)
A_{(n,m)}
A(n,m) 代表初始时有
n
n
n 条带圣盾的胖头鱼与
m
m
m 条不带圣盾的胖头鱼,消灭胖头鱼的期望造成伤害次数。考虑进行一次伤害,则有状态转移
A
(
n
,
m
)
=
1
+
m
n
+
m
A
(
n
,
m
−
1
)
+
n
n
+
m
A
(
n
+
m
−
1
,
1
)
A_{(n,m)}=1+\frac{m}{n+m}A_{(n,m-1)}+\frac{n}{n+m}A_{(n+m-1,1)}
A(n,m)=1+n+mmA(n,m−1)+n+mnA(n+m−1,1) 观察
m
=
0
m=0
m=0 的情况,此时有
A
(
n
,
0
)
=
1
+
A
(
n
−
1
,
1
)
A_{(n,0)}=1+A_{(n-1,1)}
A(n,0)=1+A(n−1,1) 考虑进一步的状态转移
A
(
n
−
1
,
1
)
=
1
+
1
n
A
(
n
−
1
,
0
)
+
n
−
1
n
A
(
n
−
1
,
1
)
A_{(n-1,1)}=1+\frac{1}{n}A_{(n-1,0)}+\frac{n-1}{n}A_{(n-1,1)}
A(n−1,1)=1+n1A(n−1,0)+nn−1A(n−1,1) 得到了一个递归的结构,则有
A
(
n
−
1
,
1
)
=
n
+
A
(
n
−
1
,
0
)
A_{(n-1,1)}=n+A_{(n-1,0)}
A(n−1,1)=n+A(n−1,0) 将其带入
m
=
0
m=0
m=0 的递推式,得到
A
(
n
,
0
)
=
A
(
n
−
1
,
0
)
+
n
+
1
A_{(n,0)}=A_{(n-1,0)}+n+1
A(n,0)=A(n−1,0)+n+1 求解得到
m
=
0
m=0
m=0 与
m
=
1
m=1
m=1 情况下的闭合表达式
A
(
n
,
0
)
=
(
n
+
3
)
n
/
2
,
A
(
n
,
1
)
=
(
n
+
3
)
n
/
2
+
n
+
1
A_{(n,0)}=(n+3)n/2,A_{(n,1)}=(n+3)n/2+n+1
A(n,0)=(n+3)n/2,A(n,1)=(n+3)n/2+n+1 在状态
(
n
,
m
)
(n,m)
(n,m) 可能转移到的两种情况中,至少有一个可以通过闭合表达式求解,递归求解即可。总时间复杂度
O
(
M
)
O(M)
O(M)。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 998244353;
ll N, M, inv2;
ll mod_pow(ll x, ll n)
{
ll res = 1 % mod;
x %= mod;
while (n)
{
if (n & 1)
res = res * x % mod;
x = x * x % mod, n >>= 1;
}
return res;
}
ll solve(ll n, ll m)
{
if (m <= 1)
{
ll res = m == 1 ? (n + 1) % mod : 0;
res += (n + 3) % mod * (n % mod) % mod * inv2 % mod;
return res % mod;
}
ll d = mod_pow(n + m, mod - 2);
ll res = 1;
res += m % mod * d % mod * solve(n, m - 1);
res += n % mod * d % mod * solve(n + m - 1, 1) % mod;
return res % mod;
}
int main()
{
inv2 = mod_pow(2, mod - 2);
cin >> N >> M;
cout << solve(N, M) << '\n';
return 0;
}