题面:
题解:
在这里,我们考虑一次吃 x x x块蛋糕的概率。
根据隔板法,我们可以求出
n
n
n块蛋糕能够生成的序列的数量为:
g ( n ) = 2 n − 1 , g ( 0 ) = 1 g(n)=2^{n-1},g(0)=1 g(n)=2n−1,g(0)=1
假设一次吃
k
k
k块蛋糕的概率为
f
(
k
)
f(k)
f(k),枚举这
k
k
k块蛋糕左右的序列可得:
f
(
k
)
=
∑
i
=
k
n
g
(
i
−
k
)
g
(
n
−
i
)
g
(
n
)
f(k)=\sum_{i=k}^n\frac {g(i-k)g(n-i)}{g(n)}
f(k)=i=k∑ng(n)g(i−k)g(n−i)
=
1
g
(
n
)
(
2
n
−
k
+
(
n
−
k
−
1
)
2
n
−
k
−
2
)
=\frac 1{g(n)}(2^{n-k}+(n-k-1)2^{n-k-2})
=g(n)1(2n−k+(n−k−1)2n−k−2)
令
P
(
x
)
=
2
x
+
(
x
−
1
)
2
x
−
2
,
P
(
0
)
=
1
P(x)=2^x+(x-1)2^{x-2},P(0)=1
P(x)=2x+(x−1)2x−2,P(0)=1,则此时答案为:
a
n
s
=
∑
k
=
1
n
f
(
k
)
k
!
=
1
g
(
n
)
∑
k
=
1
n
p
(
n
−
k
)
k
!
ans=\sum_{k=1}^n\frac {f(k)}{k!}=\frac 1{g(n)}\sum_{k=1}^n\frac {p(n-k)}{k!}
ans=k=1∑nk!f(k)=g(n)1k=1∑nk!p(n−k)
预处理 P ( x ) P(x) P(x)和逆元即可,时间复杂度 O ( n ) O(n) O(n)。
实现细节见代码:
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int MAXN = 5e5 + 10;
const int mod = 998244353;
ll f[MAXN], p[MAXN], inv[MAXN];
ll qpow(ll a, ll b) {
ll ans = 1;
while (b) {
if (b & 1) {
ans = ans * a % mod;
}
a = a * a % mod;
b >>= 1;
}
return ans;
}
void init(int n) {
f[0] = p[0] = inv[1] = 1;
for (int i = 1; i < n; i++) {
f[i] = f[i - 1] * 2 % mod;
if (i > 1)
inv[i] = (mod - (ll)mod / i) * inv[mod % i] % mod;
p[i] = (f[i] + (i - 1) * f[max(0, i - 2)] % mod) % mod;
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t;
init(500005);
cin >> t;
while (t--) {
int n;
cin >> n;
ll ans = 0;
ll cur = 1;
for (int i = 1; i <= n; i++) {
cur = cur * inv[i] % mod;
ans = (ans + p[n - i] * cur % mod) % mod;
}
ans = ans * qpow(f[n - 1], mod - 2) % mod;
cout << ans << endl;
}
return 0;
}