题目大意
有一生命值为 N N N 的怪兽,你对其攻击一次,有 1 − P 100 1-\frac P{100} 1−100P 的概率使其扣 1 1 1 点生命值,有 P 100 \frac P{100} 100P 的概率使其扣 2 2 2 点生命值。求击杀其(指其生命值不大于 0 0 0)的期望攻击次数( m o d 998244353 \bmod998244353 mod998244353)。
分析
首先你需要了解期望dp
显然,这是一个期望dp的板题。
设 f [ i ] f[i] f[i] 为怪兽生命值为 i i i 时需要击杀的期望攻击次数,明显地, f [ 0 ] = 0 f[0]=0 f[0]=0。
f [ 1 ] = 1 f[1]=1 f[1]=1,因为当其生命值为 1 1 1 时,只要进行 1 1 1 次攻击,无论是扣 1 1 1 点还是 2 2 2 点生命值,怪兽都会死亡。
由于有 1 − P 100 1-\frac P{100} 1−100P 的概率扣 1 1 1 点生命值,那么有 1 − P 100 1-\frac P{100} 1−100P 的概率由 f [ i − 1 ] f[i-1] f[i−1] 转移而来,也就是当怪兽生命值为 i i i 时,有 1 − P 100 1-\frac P{100} 1−100P 的概率有如下结果:攻击 1 1 1 次扣 1 1 1 点生命值,此时再攻击 f [ i − 1 ] f[i-1] f[i−1] 次就能杀死怪兽。
同理,当怪兽生命值为 i i i 时,有 P 100 \frac P{100} 100P 的概率有如下结果:攻击 1 1 1 次扣 2 2 2 点生命值,此时再攻击 f [ i − 2 ] f[i-2] f[i−2] 次就能杀死怪兽。
那么有
f
[
i
]
=
(
1
−
P
100
)
×
(
f
[
i
−
1
]
+
1
)
+
P
100
×
(
f
[
i
−
2
]
+
1
)
f[i]=(1-\frac P{100})\times (f[i-1]+1)+\frac P{100}\times (f[i-2]+1)
f[i]=(1−100P)×(f[i−1]+1)+100P×(f[i−2]+1)
最终输出 f [ N ] f[N] f[N].
注意这个式子是在 m o d 998244353 \bmod998244353 mod998244353 意义下的,所以对于分数 1 − P 100 = 100 − P 100 1-\frac P{100} = \frac{100-P}{100} 1−100P=100100−P 及 P 100 \frac{P}{100} 100P 都要在模意义下运算。
我们知道,费马小定理简述如下:
a
p
−
1
≡
1
(
m
o
d
p
)
a^{p-1}\equiv 1(\bmod\space p)
ap−1≡1(mod p)
其中
p
p
p 为质数。
那么有
a p − 2 ≡ a − 1 ( m o d p ) a^{p-2}\equiv a^{-1}(\bmod\space p) ap−2≡a−1(mod p)
那么
f
[
i
]
=
(
100
−
P
)
×
10
0
−
1
×
(
f
[
i
−
1
]
+
1
)
+
P
×
10
0
−
1
×
(
f
[
i
−
2
]
+
1
)
f[i]=(100-P)\times 100^{-1}\times (f[i-1]+1)+ P\times 100^{-1}\times (f[i-2]+1)
f[i]=(100−P)×100−1×(f[i−1]+1)+P×100−1×(f[i−2]+1)
=
(
100
−
P
)
×
10
0
998244353
−
2
×
(
f
[
i
−
1
]
+
1
)
+
P
×
10
0
998244353
−
2
×
(
f
[
i
−
2
]
+
1
)
=(100-P)\times 100^{998244353-2}\times (f[i-1]+1)+ P\times 100^{998244353-2}\times (f[i-2]+1)
=(100−P)×100998244353−2×(f[i−1]+1)+P×100998244353−2×(f[i−2]+1)
完毕。
code
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 200005;
const LL mod = 998244353;
int n;
LL p, f[N];
LL qpow(LL x, LL y) {
LL sum = 1;
while (y) {
if (y & 1) sum = sum * x % mod;
x = x * x % mod, y >>= 1;
}
return sum;
}
int main() {
scanf("%d%lld", &n, &p);
f[1] = 1;
for (int i = 2; i <= n; i++)
f[i] = (p * qpow(100, mod - 2) % mod * (f[i - 2] + 1) % mod + (100 - p) * qpow(100, mod - 2) % mod * (f[i - 1] + 1) % mod) % mod;
printf("%lld", f[n]);
return 0;
}
若模数为 m o d \bmod mod,
时间复杂度为 O ( N log m o d ) O(N\log\bmod) O(Nlogmod)