题目大意
有T组输入,对于每组输入一个 n(保证 n 是奇数),表示集合中有 1 到 n 的 n 个数,每次对集合删去集合中目前最小的数和随机一个数, 直到剩下最后一个数, 问每个数字被留到最后的概率。 输出对 998244353 取模。
1
暴力打表小数据然后找规律
code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=998244353;
const ll maxn=5e6+10;
ll fac[maxn];
ll invn[maxn];
ll invfac[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;
}
int init(){
int len=(int)(5e6+5);
fac[0]=fac[1]=invfac[0]=invfac[1]=invn[0]=invn[1]=1;
for(int i=2;i<=len;++i){
fac[i]=fac[i-1]*i%mod;
invn[i]=(mod-mod/i)*invn[mod%i]%mod; //逆元线性递推公式
invfac[i]=invfac[i-1]*invn[i]%mod;
}
}
ll C(ll n,ll m){ // 组合数
if(n>m) return 0;
if(n<0 || m<0) return 0;
ll res=fac[m];
res=res*invfac[m-n]%mod;
res=res*invfac[n]%mod;
return res;
}
int main(){
std::ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0); // 关同步
init(); // 预处理阶乘和逆元
int T;
cin>>T;
while(T--){
int n;
cin>>n;
if(n==1) { ///特判
cout<<1<<endl;
continue;
}
for(int i=1;i<=n/2;++i){
cout<<0<<" ";
}
for(ll i=n/2+1;i<=n;++i){
cout<<C(n/2,i-1)*qpow(qpow(2,i-1),mod-2)%mod;
if(i!=n) cout<<" ";
}
cout<<endl;
}
}