思路
组合数学+概率。其中的 (n−i)! 是对 i 后面的 (n−i) 个数进行排列,与前面选出的数进行配对。
对于前面的剩余的 i−1−(n−i)=2∗i−n−1 个数,两两进行配对选择,即每次选取 2 两个数,但由于每次配对后,每组的位置就确定了,因此要去除排列。
代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cmath>
#include <cstring>
#define ll long long
using namespace std;
const int maxn=6e6+6;
const int N=5e6+5;
ll fac[N],inv[N],cnt[N],invf[N];
const ll mod=998244353;
const ll MOD=998244353;
ll power(ll x,ll a)
{
ll ans=1;
while(a)
{
if(a&1)
{
ans=ans*x%mod;
}
x=x*x%mod;
a>>=1;
}
return ans;
}
void init()
{
fac[0]=1;
for(int i=1;i<N;i++)
fac[i]=fac[i-1]*i%mod;
invf[N-5]=power(fac[N-5],mod-2);
for(int i=N-6;i>=0;i--)
invf[i]=invf[i+1]*(i+1)%mod;
inv[0]=1;
inv[1]=1LL*499122177;
for(int i=2;i<N;i++)
inv[i]=inv[i-1]*inv[1]%mod;
}
int main()
{
int T,n;
init();
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
ll sum=0;
for(int i=1;i<=n/2;i++) cnt[i]=0;
for(int i=n/2+1;i<=n;i++)
{
cnt[i]=fac[i-1]*inv[(2*i-n-1)/2]%mod*invf[(2*i-n-1)/2]%mod;
sum=(sum+cnt[i])%mod;
}
ll inv_sum=power(sum,mod-2);
for(int i=1;i<=n;i++)
printf("%lld%c",cnt[i]*inv_sum%mod,i==n?'\n':' ');
}
return 0;
}