$\newcommand{\align}[1]{\begin{align*}#1\end{align*}}$ Meaning: For a permutation $p_{1\cdots n}$ constructs a graph, if $i\ lt j$ and $p_i\lt p_j$, even the bidirectional edge $(i,j)$, the weight of this permutation is the product of the sizes of all connected blocks, and the sum of the weights of all $n!$ permutations
Considering DP, let $f_n$ represent the number of connected solutions (a graph composed of permutations of length $n$), then we can use $n!$ to subtract the number of disconnected solutions, and consider the illegal solutions as the first The size of connected blocks $i$ is classified, then the number of $ni$ can be randomly arranged, so $\align{f_n=n!-\sum\limits_{i=1}^{n-1}(ni)! f_i}$
Let the answer be $g_n$, enumerating the size $i$ of the last connected block, we get the shift $\align{g_n=\sum\limits_{i=1}^nif_ig_{ni}}$
Doing this is $O(n^2)$, considering optimization
First convert the recursion of $f$, $\align{2n!=[n=0]+\sum\limits_{i=0}^n(ni)!f_i}$
设$\align{A(x)=\sum\limits_ii!x^i,B(x)=\sum\limits_if_ix^i}$,则$2A(x)=A(x)B(x)+1$,即$B(x)=\dfrac{2A(x)-1}{A(x)}$
Direct polynomial inversion can calculate $B(x)$, set $\align{C(x)=\sum\limits_iif_ix^i}$, now consider calculating the answer, enumerate the number of connected blocks in the answer $k$, The answer is $\align{[x^n]\sum\limits_{i=1}^\infty C^k(x)=[x^n]\left(\dfrac1{1-C(x)}-1 \right)}$, calculate $C(x)$ and then inverse it
But the cancer yww put it out to $n\leq5\times10^5$, if it is written in this way, it will drop T, so let's come to Kaka often==
First notice that $C(x)$ is actually an extra $i$ for each coefficient of $B(x)$, so $C(x)=xB'(x)$, and then use $B(x) =\dfrac{2A(x)-1}{A(x)}$, we get $\dfrac1{1-C(x)}=\dfrac{A^2(x)}{A^2(x) -xA'(x)}$, optimized to only use two FFTs and one polynomial inversion, which can be passed
We can continue to optimize, we need to find a way to quickly calculate $\align{h_n=[x^n]A^2(x)=\sum\limits_{i=0}^ni!(ni)!}$, in The recursive formula $h_n=n!+\dfrac{n+1}2h_{n-1}$ can be found on OEIS , but I haven’t found a proof to see if there is a chance to fill the pit in the future, so I can just do first degree polynomial inversion
#include<stdio.h> #include<string.h> const int mod=998244353,maxn=1048576; typedef long long ll; int mul(int a,int b){return a*(ll)b%mod;} int ad(int a,int b){return(a+b)%mod;} int de(int a,int b){return(a-b)%mod;} int pow(int a,int b){ int s=1; while(b){ if(b&1)s=mul(s,a); a=mul(a,a); b>>=1; } return s; } int rev[maxn],N,iN; void pre(int n){ int i,k; for(N=1,k=0;N<n;N<<=1)k++; for(i=0;i<N;i++)rev[i]=(rev[i>>1]>>1)|((i&1)<<(k-1)); iN=pow(N,mod-2); } void swap(int&a,int&b){a^=b^=a^=b;} void ntt(int*a,int on){ int i,j,k,t,w,wn; for(i=0;i<N;i++){ if(i<rev[i])swap(a[i],a[rev[i]]); } for(i=2;i<=N;i<<=1){ wn=pow(3,(on==1)?(mod-1)/i:(mod-1-(mod-1)/i)); for(j=0;j<N;j+=i){ w=1; for(k=0;k<i>>1;k++){ t=mul(w,a[i/2+j+k]); a [i/2+j+k] = de (a [j+k], t); a[j+k]=ad(a[j+k],t); w=mul(w,wn); } } } if(on==-1){ for(i=0;i<N;i++)a[i]=mul(a[i],iN); } } int t[maxn]; void getinv(int*a,int*b,int n){ if(n==1){ b[0]=pow(a[0],mod-2); return; } int i; getinv(a,b,n>>1); pre(n<<1); memset(t,0,N<<2); memcpy(t,a,n<<2); ntt(t,1); ntt(b,1); for(i=0;i<N;i++)b[i]=mul(b[i],2-mul(b[i],t[i])); ntt(b,-1); for(i=n;i<N;i++)b[i]=0; } int a[maxn],b[maxn],c[maxn]; int main(){ int n,k,i,years; scanf("%d",&n); for(k=1;k<=n;k<<=1); a[0]=1; for(i=1;i<=n;i++){ a[i]=mul(i,a[i-1]); b[i]=mul(i,a[i]); } pre(k<<1); ntt(a,1); for(i=0;i<N;i++)a[i]=mul(a[i],a[i]); ntt(a,-1); for(i=0;i<=n;i++)b[i]=de(a[i],b[i]); getinv(b,c,k); years=0; for(i=0;i<=n;i++)ans=ad(ans,mul(a[i],c[n-i])); printf("%d",ad(ans,mod)); }