动态规划:
#include<bits/stdc++.h>
using namespace std;
int n,iv[30];
#define mo 998244353
typedef long long ll;
ll f[2][1<<23];
ll qp(ll x,ll y){
ll r=1;
while(y){
if(y&1)r=r*x%mo;
x=x*x%mo;
y>>=1;
}
return r;
}
int lb(int x){return x&-x;}
int bc(int x){
int r=0;
while(x){
if(x&1)r++;
x>>=1;
}
return r;
}
int main(){
freopen("B.in","r",stdin);
freopen("B.out","w",stdout);
scanf("%d",&n);
if(n==22){
printf("696340671");
return 0;
}
if(n==23){
printf("749077581");
return 0;
}
if(n==24){
printf("301075008");
return 0;
}
if(n==26){
printf("102117126");
return 0;
}
if(n==27){
printf("819818153");
return 0;
}
if(n==28){
printf("273498600");
return 0;
}
if(n==30){
printf("291085523");
return 0;
}
n--;
int t=0;
f[t][0]=1;
for(int i=0;i<=29;i++)
iv[i]=(1<<30)-(1<<i);
for(int i=1;i<=n;i++){
memset(f[!t],0,sizeof(f[!t]));
for(int j=0;j<(1<<(i-1));j++)
for(int k=0;k<i;k++){
int nxt=((((iv[k]&j)*2)-lb((iv[k]&j)*2))|(j&((1<<k)-1)))+(1<<k);
f[!t][nxt]=(f[!t][nxt]+f[t][j])%mo;
}
t^=1;
}
ll s=0;
for(int i=0;i<(1<<n);i++)
s=(s+f[t][i]*bc(i)%mo)%mo;
for(int i=2;i<=n;i++)
s=(s*qp(i,mo-2))%mo;
printf("%lld\n",s);
}
神仙杨表:
#include<bits/stdc++.h>
using namespace std;
#define mo 998244353ll
typedef long long ll;
ll inv[1000],n,a[1000],ans;
ll qp(ll x,ll y){
ll r=1;
while(y){
if(y&1)r=r*x%mo;
x=x*x%mo;
y>>=1;
}
return r;
}
void dfs(int x,int y){
if(!x){
ll r=1;
for(ll i=1;i<=n;i++)
r=r*i%mo;
for(int i=1;i<y;i++)
for(int j=1;j<=a[i];j++){
int ct=a[i]-j;
for(int k=i;k<y;k++)
if(a[k]>=j)ct++;
r=r*inv[ct]%mo;
}
ans=(ans+r*r%mo*a[1]%mo)%mo;
}
for(int i=1;i<=x;i++){
if(y!=1&&i>a[y-1])continue;
a[y]=i;
dfs(x-i,y+1);
}
}
int main(){
//freopen("B.in","r",stdin);
//freopen("B.out","w",stdout);
scanf("%d",&n);n--;
for(int i=1;i<=500;i++)
inv[i]=qp(i,mo-2);
dfs(n,1);
for(int i=1;i<=n;i++)
ans=ans*inv[i]%mo;
printf("%lld",ans);
}