P6858 深海少女与胖头鱼
知识点:概率期望,DP
P6858 深海少女与胖头鱼
原题面:Luogu。
扯
我不会期望/cy
草好久没打炉石了,回去搓一把。
题意简述
对面有 \(n\) 只带有「圣盾」的「鲭鱼圣者」,\(m\) 只不带「圣盾」的「鲭鱼圣者」。
每次可以等概率地对场上一只「鲭鱼圣者」造成伤害。
「圣盾」可以抵挡一次伤害,可以立即杀死不带「圣盾」的「鲭鱼圣者」。
每当一个「鲭鱼圣者」失去「圣盾」时,其他 所有存活的「鲭鱼圣者」都会获得「圣盾」。
求杀死所有「鲭鱼圣者」的其期望攻击次数 \(\bmod 998244353\) 的值。\(1\le n\le 10^{14}\),\(0\le m\le 10^6\)。
保证答案的形式 \(\frac{p}{q}\) 满足 \((p,q\in \mathbf{N}\),\(998244353\nmid q)\)。
1S,128MB。
分析题意
先考虑 \(m=0\) 的情况,显然此时场上没有盾的鱼人最多只有 1 条。
考虑 DP,设 \(f_{n,0/1}\) 表示干掉 \(n\) 条带盾的鱼人,\(0/1\) 条不带盾的鱼人所需攻击次数的期望。
显然有:\(f_{0,0} = 0\),\(f_{0,1} = 1\)。
转移时考虑从一个状态攻击一次能达到的状态,有:
对于一式的情况,此时只能攻击一个带盾的鱼人,削除该鱼人的盾。其攻击次数为削除该鱼人的盾后需要的次数 + 1。
对于二式的情况,若以 \(\frac{i}{i+1}\) 的概率攻击了一条带有圣盾的鱼人,还会转移到相同的状态。
若以 \(\frac{1}{i+1}\) 的概率攻击了不带盾的鱼人,则会转移到削除该鱼人的状态。
发现上面的方程转移不来,化下二式:
得到了 \(f_{i,1}\) 与 \(f_{i,0}\) 的关系。 再将一式代入,有:
显然是一个等差数列求和的形式,由 \(f_{0,1} = 1\),则有(具体推导过程见最后):
预处理 2 的逆元后,可以 \(O(1)\) 地求得 \(m=1\) 时的答案 \(f_{n,0}\) 了。
再推广到 \(m\not = 1\) 的情况。
更一般性地,设 \(f_{n,m}\) 表示干掉 \(n\) 条带盾的鱼人,\(m\) 条不带盾的鱼人所需攻击次数的期望。
由上显然有:
上式中的前一项 \(f_{n+m-1,1}\) 可以 \(O(1)\) 求,后面一项可以递推。
每次都 \(O(\log p)\) 地求逆元,总复杂度 \(O(m\log p)\)。
爆零小技巧
等差数列求和公式:
注意 \(n\le 10^{18}\),需要先令 \(n\bmod 998244353\),否则必爆 LL。
代码实现
//知识点:概率期望,等差数列
/*
By:Luckyblock
*/
#include <cctype>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define LL long long
const int kMaxm = 1e6 + 10;
const LL kMod = 998244353ll;
//=============================================================
LL n, m, inv2, f[kMaxm];
//=============================================================
inline LL read() {
LL f = 1, w = 0; char ch = getchar();
for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
for (; isdigit(ch); ch = getchar()) w = (w << 3ll) + (w << 1ll) + (ch ^ '0');
return f * w;
}
LL QPow(LL x_, LL y_) {
LL ret = 1;
for (; y_; y_ >>= 1ll) {
if (y_ & 1) ret = ret * x_ % kMod;
x_ = x_ * x_ % kMod;
}
return ret;
}
LL fx0(LL x_) {
x_ %= kMod;
return x_ * (x_ + 3ll) % kMod * inv2 % kMod;
}
LL fx1(LL x_) {
x_ %= kMod;
return (x_ * (x_ + 5ll) % kMod + 2ll) * inv2 % kMod;
}
//=============================================================
int main() {
n = read() % kMod, m = read();
inv2 = QPow(2ll, kMod - 2);
f[0] = fx0(n);
for (int i = 1; i <= m; ++ i) {
LL inv = QPow(n + i, kMod - 2) % kMod;
LL fni = fx1(n + i - 1);
f[i] = n * inv % kMod * fni % kMod;
f[i] = (f[i] + i * inv % kMod * f[i - 1] % kMod + 1) % kMod;
}
printf("%lld\n", f[m]);
return 0;
}
某数列忘干净的 sb 的推导
以下是数列忘干净的傻逼的有误推导 = =
???我哪错了???
以上是数列忘干净的傻逼的有误推导 = =
关于 \(f_n=\frac{n(n+5) + 2}{2}\):
已知:
左右两边分别求和,则有:
对应项相消,有: