原题链接:Set1
题面:
题目大意:
给定一个集合
S
=
{
1
∼
n
}
S=\{1\sim n\}
S={1∼n},对集合进行如下操作直到
∣
S
∣
=
1
|S|=1
∣S∣=1。
首先会先删除集合中最小的数,之后以相同的概率删除其他的数。
求集合中每一个数被保留下来的概率。
数学推导:
令操作 1 1 1为删除最小的元素,操作 2 2 2为随机删除一个元素。
假设元素 i i i 会被保留下来,则它的前面有 i − 1 i-1 i−1 个元素,后面有 n − i n-i n−i 个元素。我们需要考虑保留下元素 i i i 的所有方案数。
显然,保留下 i i i 必须满足的条件是: n − i ≤ i − 1 n-i\leq i-1 n−i≤i−1。这样,我们可以知道,当 i ≤ n 2 i\leq \frac{n}{2} i≤2n 时, i i i 是必定会被删除的。而且,后面 n − i n-i n−i 个元素必然是经过操作2删除的。
所以,在所有
i
i
i 被保留下来的情况中,后面
n
−
i
n-i
n−i 个元素必然是与前面
i
−
1
i-1
i−1 个元素中的
n
−
i
n-i
n−i 个元素一一对应被删去的。
所以,我们可以得到删除后面
n
−
i
n-i
n−i 个元素的方案数为:
C
n
−
1
i
−
1
∗
A
n
−
i
n
−
i
=
A
i
−
1
n
−
i
=
(
i
−
1
)
!
(
2
∗
i
−
n
−
1
)
!
C_{n-1}^{i-1}*A_{n-i}^{n-i}=A_{i-1}^{n-i}=\cfrac{(i-1)!}{(2*i-n-1)!}
Cn−1i−1∗An−in−i=Ai−1n−i=(2∗i−n−1)!(i−1)!
删除后面
n
−
i
n-i
n−i 个元素后,还剩下
2
∗
i
−
n
−
1
2*i-n-1
2∗i−n−1 个元素没有删去,所以我们需要两两删除这些剩余的元素。
两两删除的方案数为:
C
2
i
−
n
−
1
2
∗
C
2
i
−
n
−
3
2
∗
.
.
.
∗
C
2
2
=
(
2
i
−
n
−
1
)
!
2
!
2
i
−
n
−
1
2
C_{2i-n-1}^{2}*C_{2i-n-3}^{2}*...*C_{2}^{2}=\cfrac{(2i-n-1)!}{2!^{\frac{2i-n-1}{2}}}
C2i−n−12∗C2i−n−32∗...∗C22=2!22i−n−1(2i−n−1)!
其中,由于选择存在顺序不一样,但是删除的元素重复的问题。所以,我们还需要进行去重操作。即需要除以
(
2
i
−
n
−
1
2
)
!
(\frac{2i-n-1}{2})!
(22i−n−1)!。
最终得到的 i i i 被保留下来的方案数为: c n t [ i ] = ( i − 1 ) ! ( 2 ! ) 2 i − n − 1 2 ∗ ( 2 i − n − 1 2 ) ! cnt[i]=\cfrac{(i-1)!}{(2!)^\frac{2i-n-1}{2}*(\frac{2i-n-1}{2})!} cnt[i]=(2!)22i−n−1∗(22i−n−1)!(i−1)!
总方案数
s
u
m
=
∑
i
=
1
n
c
n
t
[
i
]
sum=\sum_{i=1}^{n}cnt[i]
sum=∑i=1ncnt[i]
所以,元素
i
i
i 被保留的概率
p
[
i
]
=
c
n
t
[
i
]
s
u
m
p[i]=\cfrac{cnt[i]}{sum}
p[i]=sumcnt[i]
这样,我们只需要预处理一下阶乘和逆元就行了。
代码:
#include <bits/stdc++.h>
#define sc scanf
#define pf printf
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
const int N = 5e6 + 10, M = 2e4 + 10;
const int INF = 0x3f3f3f3f;
const double eps = 1e-7;
const int mod = 998244353;
LL fac[N], inv[N], invf[N], cnt[N];
LL qmi(LL a, LL b)
{
LL ans = 1 % mod;
for( ; b; b >>= 1) {
if(b & 1) ans = ans * a % mod;
a = a * a % mod;
}
return ans;
}
void init()
{
fac[0] = inv[0] = 1;
for(int i = 1; i < N; i++) {
fac[i] = fac[i - 1] * i % mod;
inv[i] = inv[i - 1] * qmi(i, mod - 2) % mod;
}
}
void solve()
{
int n;
sc("%d", &n);
if(n == 1) pf("1");
else {
LL sum = 0;
for(int i = 1; i <= n >> 1; i++) pf("0 ");
for(int i = n / 2 + 1; i <= n; i++) {
cnt[i] = fac[i - 1] * qmi(inv[2], (2 * i - n - 1) / 2) % mod * inv[(2*i-n-1)/2] % mod;
sum = (sum + cnt[i]) % mod;
}
sum = qmi(sum, mod - 2);
for(int i = n / 2 + 1; i <= n; i++) {
if(i == n / 2 + 1) pf("%lld", sum * cnt[i] % mod);
else pf(" %lld", sum * cnt[i] % mod);
}
}
puts("");
}
int main()
{
init();
int t; sc("%d", &t); while(t--) solve();
return 0;
}