卧薪尝胆,厚积薄发。
Complete the Permutations
Date: Sun Dec 30 22:05:05 CST 2018
In Category:
NoCategory
Description:
给定两个排列
$p,q$
,但是其中有些位置未知。补全两个排列,定义两个排列
$p,q$
之间的距离为每次选择
$p$
中两个元素交换,使其变成
$q$
的最小次数。对于
$i \in [0,n-1]$
求出补全后相似度为
$i$
的方案数。
$1\leqslant n\leqslant 250$
Solution:
首先假设排列没有未知元素,那么两个排列都可以看成一个置换,要求的实际上就是
$n-$
这两个置换的和的环的个数,因为最终一定是沿着环交换,转化成图论就是连边
$p_i\to q_i$
,求图中环的个数,那么我们先把已知的构造出来,对于一整个环,我们可以答案
$+1$
直接删掉,记这个的个数为
$cyc$
,然后就是链的情况,发现我们实际上只要知道链的两个端点就可以了,链之间的点不会产生影响,那么我们可以按两端的情况分成
$x\to ?,?\to x,?\to ?$
三种可能先一遍
$dfs$
算出他们的个数分别为
$cnt1,cnt2,cnt4$
,
$m=cnt1+cnt2+cnt4$
,然后就可以列答案的式子了:
$$
f_x=\sum_{o_1=0}^x\sum_{k_1=o_1}^{cnt_1}\sum_{o_2=0}^{x-o_1}\sum_{k_2=o_2}^{cnt_2}
C^{cnt_1}_{k_1}S_1(k_1,o_1)C^{cnt_2}_{k_2}S_1(k_2,o_2)
P^{cnt_1-k_1+cnt_4-1}_{cnt_1-k_1}P^{cnt_2-k_2+cnt_4}_{cnt_2-k_2}S_1(cnt_4,x-o_1-o_2)cnt4!
$$
$f_k$
表示有
$k$
个环的方案数,然后先枚举只用
$x\to ?$
组成的环的个数
$o_1$
,所用的个数
$k_1$
,然后再枚举只用
$?\to x$
组成的环的个数
$o_2$
和所用的个数
$k_2$
,因为如果这两个放在一起组成环,那么中间一定夹着
$?\to?$
这样的链,所以我们把环按是否有
$?\to?$
分类讨论,然后那两种链和
$?\to ?$
组合可以看成是把某条链接在
$?\to?$
的一边,形成一个更大的
$?\to?$
链,那两种链一定分别接在
$?\to?$
链的两侧所以互不影响。然后发现还是可以把两种链分别考虑,一个的方案数就是把
$x\to?/?\to x$
和
$?\to?$
排序的方案数,也就是类似球相同桶不同可以空的计算方法,但是球也是不同的,所以是一个排列数,显然是
$P^{cnt_1-k_1+cnt_4}_{cnt_1-k_1}$
,而且桶还要乘上一个
$cnt_4!$
因为互换之后是另一种方案,这样最后还相当于是
$cnt4$
个
$?\to?$
的链,他们应该排成
$x-o_1-o_2$
个轮换,所以方案数就是第一类斯特林数了。
先设:
$$
a[i]=\sum_{k_1=i}^{cnt_1}C^{cnt_1}_{k_1}S_1(k_1,i)P^{cnt_1-k_1+cnt_4-1}_{cnt_1-k_1}\\
b[i]=\sum_{k_2=i}^{cnt_2}C^{cnt_2}_{k_2}S_1(k_2,i)P^{cnt_2-k_2+cnt_4-1}_{cnt_2-k_2}\\
$$
这两个可以
$O(n^2)$
求
$$
c[x]=\sum_{i=0}^xa[i]b[x-i]
$$
这个也可以
$O(n^2)$
求
$$
f[x]=\sum_{i=0}^xc[i]S_1(cnt_4,x-i)cnt4!
$$
也是
$O(n^2)$
求。
复杂度主要就是在求
$a[i]$
和
$b[i]$
的时候,别的都可以优化。
Code:
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cctype>
#include<cstring>
using namespace std;
int n;
#define MAXN 510
#define MOD 998244353
int p[MAXN],q[MAXN];
bool vis[MAXN];
int nxt[MAXN];
int ind[MAXN];
int cnt1 = 0,cnt2 = 0,cnt3 = 0,cnt4 = 0;
void dfs(int k,int rt)
{
vis[k] = true;
if(nxt[k] != 0)
{
if(!vis[nxt[k]])dfs(nxt[k],rt);
else ++cnt3;
}
else
{
if(rt > n && k > n)++cnt4;
else if(rt <= n && k > n)++cnt1;
else if(rt > n && k <= n)++cnt2;
}
return;
}
int P[MAXN][MAXN],C[MAXN][MAXN],S[MAXN][MAXN];
void init()
{
S[0][0] = P[0][0] = C[0][0] = 1;
for(int i = 1;i <= n;++i)
{
C[i][0] = P[i][0] = 1;
for(int j = 1;j <= i;++j)
{
C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % MOD;
P[i][j] = (1ll * j * P[i - 1][j - 1] + P[i - 1][j]) % MOD;
S[i][j] = (1ll * (i - 1) * S[i - 1][j] + S[i - 1][j - 1]) % MOD;
}
}
return;
}
int a[MAXN],b[MAXN],c[MAXN],f[MAXN];
int main()
{
scanf("%d",&n);
for(int i = 1;i <= n;++i)scanf("%d",&p[i]);
for(int i = 1;i <= n;++i)scanf("%d",&q[i]);
for(int i = 1;i <= (n << 1);++i)vis[i] = true;
for(int i = 1;i <= n;++i)
{
int x = (p[i] ? p[i] : i + n);
int y = (q[i] ? q[i] : i + n);
vis[x] = vis[y] = false;
if(x <= n || y <= n)
{
nxt[x] = y;
++ind[y];
}
}
for(int i = 1;i <= (n << 1);++i)
{
if(!vis[i] && ind[i] == 0)dfs(i,i);
}
for(int i = 1;i <= (n << 1);++i)
{
if(!vis[i])dfs(i,i);
}
init();
if(cnt4)
{
for(int i = 0;i <= cnt1;++i)
{
for(int k = i;k <= cnt1;++k)
{
a[i] = (a[i] + 1ll * C[cnt1][k] * S[k][i] % MOD * P[cnt1 - k + cnt4 - 1][cnt1 - k] % MOD) % MOD;
}
}
for(int i = 0;i <= cnt2;++i)
{
for(int k = i;k <= cnt2;++k)
{
b[i] = (b[i] + 1ll * C[cnt2][k] * S[k][i] % MOD * P[cnt2 - k + cnt4 - 1][cnt2 - k] % MOD) % MOD;
}
}
}
else
{
for(int i = 0;i <= cnt1;++i)a[i] = S[cnt1][i];
for(int i = 0;i <= cnt2;++i)b[i] = S[cnt2][i];
}
//for(int i = 0;i <= cnt1;++i)cout << a[i] << " ";cout << endl;
//for(int i = 0;i <= cnt2;++i)cout << b[i] << " ";cout << endl;
for(int i = 0;i <= n;++i)
{
for(int j = 0;j <= i;++j)
{
c[i] = (c[i] + 1ll * a[j] * b[i - j]) % MOD;
}//cout << c[i] << " ";
}//cout << endl;
for(int i = 0;i <= n;++i)
{
for(int j = 0;j <= i;++j)
{
f[i] = (f[i] + 1ll * c[j] * S[cnt4][i - j]) % MOD;
}
}
int fac = 1;
for(int i = 1;i <= cnt4;++i)fac = 1ll * fac * i % MOD;
for(int i = 0;i < n;++i)
{
if(n - i - cnt3 < 0)printf("0 ");
else printf("%d ",1ll * f[n - i - cnt3] * fac % MOD);
}
puts("");
return 0;
}
In tag:
数学-组合数学-斯特林数
Copyright © 2020
wjh15101051
ღゝ◡╹)ノ♡