分析
先考虑所有 $n$ 个点竞赛图的哈密顿回路数之和。可以发现为
$$
(n-1)!2^{{n\choose 2}-n}
$$
意思是钦定一个起点(否则会算重),然后哈密顿回路有 $(n-1)!$ 种,剩下的 $2^{{n\choose 2}-n}$ 条边可以任意定向。
再考虑 $n$ 个点的值得记录的竞赛图数。可以发现这个东西等价于 $n$ 个点的强连通竞赛图数。
我们设 $f_n$ 为 $n$ 个点的竞赛图数,$g_n$ 为 $n$ 个点的强连通竞赛图数,则有
$$
\begin{cases}
f_n=2^{n\choose 2}\\
g_n=f_n-\sum_{i=1}^{n-1}{n\choose i}g_if_{n-i}
\end{cases}
$$
下面那个式子的意思是枚举拓扑序最小的强连通分量的大小,然后这个强连通分量往后面连的边的方向就确定了。
把下面的式子移项得到
$$
f_n=\sum_{i=1}^n{n\choose i}g_if_{n-i}
$$
是一个二项卷积的形式,这启发我们设 EGF $F(x)=\sum_{i\geq 0}f_i\frac{x^i}{i!}$,$G(x)=\sum_{i\geq 0}g_i\frac{x^i}{i!}$。
于是有
$$
F(x)=F(x)G(x)+1
$$
即
$$
G(x)=1-\frac{1}{F(x)}
$$
多项式求逆即可。
代码
// ====================================
// author: M_sea
// website: https://m-sea-blog.com/
// ====================================
#include <bits/stdc++.h>
#define file(x) freopen(#x".in","r",stdin); freopen(#x".out","w",stdout)
#define debug(...) fprintf(stderr,__VA_ARGS__)
using namespace std;
typedef long long ll;
int read() {
int X=0,w=1; char c=getchar();
while (c<'0'||c>'9') { if (c=='-') w=-1; c=getchar(); }
while (c>='0'&&c<='9') X=X*10+c-'0',c=getchar();
return X*w;
}
const int N=400000+10;
const int mod=998244353;
int qpow(int a,int b) { int c=1;
for (;b;b>>=1,a=1ll*a*a%mod) if (b&1) c=1ll*c*a%mod;
return c;
}
int r[N];
void NTT(int* A,int n,int op) {
for (int i=0;i<n;++i) if (i<r[i]) swap(A[i],A[r[i]]);
for (int i=1;i<n;i<<=1) {
int rot=qpow(op==1?3:332748118,(mod-1)/(i<<1));
for (int j=0;j<n;j+=i<<1)
for (int k=0,w=1;k<i;++k,w=1ll*w*rot%mod) {
int x=A[j+k],y=1ll*w*A[j+k+i]%mod;
A[j+k]=(x+y)%mod,A[j+k+i]=(x-y+mod)%mod;
}
}
if (op==-1) { int inv=qpow(n,mod-2);
for (int i=0;i<n;++i) A[i]=1ll*A[i]*inv%mod;
}
}
int NTT_init(int n) {
int lim=1,l=-1;
for (;lim<=n;lim<<=1,++l);
for (int i=0;i<lim;++i) r[i]=(r[i>>1]>>1)|((i&1)<<l);
return lim;
}
void getinv(int* F,int* G,int n) {
static int A[N],B[N];
if (n==1) { G[0]=qpow(F[0],mod-2); return; }
getinv(F,G,n>>1);
for (int i=0;i<n;++i) A[i]=F[i],B[i]=G[i];
int lim=NTT_init(n);
NTT(A,lim,1),NTT(B,lim,1);
for (int i=0;i<lim;++i) A[i]=1ll*A[i]*B[i]%mod*B[i]%mod;
NTT(A,lim,-1);
for (int i=0;i<n;++i) G[i]=(2ll*G[i]-A[i]+mod)%mod;
for (int i=0;i<lim;++i) A[i]=B[i]=0;
}
int n,fac[N],ifac[N],F[N],G[N],H[N];
int main() {
n=read();
fac[0]=1;
for (int i=1;i<=n;++i) fac[i]=1ll*fac[i-1]*i%mod;
ifac[n]=qpow(fac[n],mod-2);
for (int i=n;i;--i) ifac[i-1]=1ll*ifac[i]*i%mod;
for (int i=0;i<=n;++i)
F[i]=1ll*qpow(2,1ll*i*(i-1)/2%(mod-1))*ifac[i]%mod;
int lim=1; for (;lim<=n;lim<<=1);
getinv(F,H,lim);
for (int i=3;i<=n;++i) G[i]=mod-H[i];
if (n>=1) puts("1");
if (n>=2) puts("-1");
for (int i=3;i<=n;++i) {
int s=1ll*fac[i-1]*qpow(2,(1ll*i*(i-1)/2-i)%(mod-1))%mod;
int c=1ll*G[i]*fac[i]%mod;
printf("%d\n",1ll*s*qpow(c,mod-2)%mod);
}
return 0;
}