C F 715 E CF715E CF715E
- 对于全部确定的情况,算出
n
n
n - 环数 即可
对于全部不确定的情况, a n s i = s n , i n ! ans_i=s_{n,i}n! ansi=sn,in!
否则考虑 p i p_i pi 向 q i q_i qi 连边,原图相当于若干条链(以及环,已经成环可以不管了),形如 ( 0 , 0 ) , ( a , 0 ) , ( 0 , a ) , ( a , b ) (0,0),(a,0),(0,a),(a,b) (0,0),(a,0),(0,a),(a,b),对于第 4 类对方案数没有贡献
分类记为 a , b , c a,b,c a,b,c, b b b 类可以自己和自己拼接,枚举其个数以及环数,剩余的考虑与 ( 0 , 0 ) (0,0) (0,0) 拼接,注意到 ( a , 0 ) (a,0) (a,0) 可以与 ( 0 , 0 ) (0,0) (0,0) 拼接成 ( 0 , 0 ) (0,0) (0,0),写成对其环个数的 O G F OGF OGF
拼接时 b b b 带标号,先让 a a a 无标号,最后考虑其标号,方案数是个插板
F ( x ) = ∑ i = 0 b x i ∑ j = i b ( b j ) s j , i ( a − 1 + j − i j − i ) ( j − i ) ! F(x)=\sum_{i=0}^bx^i\sum_{j=i}^b\binom{b}{j}s_{j,i}\binom{a-1+j-i}{j-i}(j-i)! F(x)=i=0∑bxij=i∑b(jb)sj,i(j−ia−1+j−i)(j−i)!
c c c 类同理, a a a 类的 O G F OGF OGF 也可以简单写出(考虑标号)
G ( x ) = ∑ i = 0 a a ! s a , i x i G(x)=\sum_{i=0}^a a!s_{a,i}x^i G(x)=i=0∑aa!sa,ixi
#include<bits/stdc++.h>
#define cs const
#define pb push_back
using namespace std;
cs int Mod = 998244353;
int add(int a, int b){ return a + b >= Mod ? a + b - Mod : a + b; }
int dec(int a, int b){ return a - b < 0 ? a - b + Mod : a - b; }
int mul(int a, int b){ return 1ll * a * b % Mod; }
void Mul(int &a, int b){ a = mul(a,b); }
void Add(int &a, int b){ a = add(a,b); }
void Dec(int &a, int b){ a = dec(a,b); }
int ksm(int a, int b){ int as=1; for(;b;b>>=1,Mul(a,a))if(b&1)Mul(as,a); return as; }
cs int N = 5e3 + 50;
int n, a[N], b[N], in[N], out[N];
int A, B, C, D, to[N];
int S[N][N], f[N], g[N], h[N];
int fc[N], ifc[N];
int Binom(int n, int m){ if(n<0||m<0||n<m) return 0; return mul(fc[n],mul(ifc[n-m],ifc[m])); }
int anc[N], sz[N], ec[N];
int fnd(int x){ return x == anc[x] ? x : anc[x] = fnd(anc[x]); }
void mrg(int x, int y){
int fx = fnd(x), fy = fnd(y); ++ec[fx];
if(fx==fy) return;
ec[fx]+=ec[fy]; sz[fx]+=sz[fy];
anc[fy] = fx;
}
int main(){
#ifdef FSYolanda
freopen("1.in","r",stdin);
#endif
scanf("%d",&n);
for(int i=1; i<=n; i++)
scanf("%d",&a[i]);
for(int i=1; i<=n; i++)
scanf("%d",&b[i]);
for(int i=1; i<=n; i++) anc[i]=i,sz[i]=1;
for(int i=1; i<=n; i++) if(a[i] && b[i]) mrg(a[i],b[i]);
static bool ea[N], eb[N], da[N], db[N];
for(int i=1,u,v; i<=n; i++){
u=fnd(a[i]),v=fnd(b[i]);
if(a[i] && b[i] && u==v){
if(u==a[i] && ec[u]==sz[u]) ++D;
} a[i]=u; b[i]=v;
if(a[i] && b[i]!=a[i])
ea[a[i]] = true, da[a[i]] = !!b[i];
if(b[i] && b[i]!=a[i])
eb[b[i]] = true, db[b[i]] = !!a[i];
}
for(int i=1; i<=n; i++)
if(!a[i] && !b[i]) ++A;
for(int i=1; i<=n; i++){
if(ea[i] && eb[i] && !da[i] && !db[i]) ++A;
else{
if(ea[i] && !da[i]) ++B;
if(eb[i] && !db[i]) ++C;
}
}
S[0][0] = 1;
for(int i=1; i<=n; i++)
for(int j=1; j<=i; j++)
S[i][j]=add(S[i-1][j-1],mul(S[i-1][j],i-1));
fc[0]=ifc[0]=fc[1]=ifc[1]=1;
for(int i=2; i<=n; i++) fc[i]=mul(fc[i-1],i);
ifc[n]=ksm(fc[n],Mod-2);
for(int i=n-1; i>=2; i--) ifc[i]=mul(ifc[i+1],i+1);
for(int i=0; i<=B; i++){
if(!A) f[i]=S[B][i];
else for(int j=i; j<=B; j++)
Add(f[i],mul(mul(Binom(B,j),S[j][i]),mul(Binom(A-1+B-j,A-1),fc[B-j])));
}
for(int i=0; i<=C; i++){
if(!A) g[i]=S[C][i];
else for(int j=i; j<=C; j++)
Add(g[i],mul(mul(Binom(C,j),S[j][i]),mul(Binom(A-1+C-j,A-1),fc[C-j])));
}
static int ans[N], tmp[N];
for(int i=0; i<=B; i++)
for(int j=0; j<=C; j++)
Add(tmp[i+j],mul(f[i],g[j]));
for(int i=0; i<=A; i++)
h[i] = mul(fc[A],S[A][i]);
for(int i=0; i<=B+C; i++)
for(int j=0; j<=A; j++)
Add(ans[i+j],mul(h[j],tmp[i]));
for(int i=n; i>=D; i--) ans[i] = ans[i-D];
for(int i=D-1; i>=0; i--) ans[i] = 0;
for(int i=0; i<n; i++)
cout<<ans[n-i]<<" ";
return 0;
}