康托展开学习笔记


什么是康托展开

给出一个全排列,求它是第几个全排列,叫做康托展开。

给出全排列长度和它是第几个全排列,求这个全排列,叫做逆康托展开。

如何康托展开

我们看这样一个序列 \([2,5,3,4,1]\)

我们考虑求出比这个序列字典序小的序列个数

首先,以 \(1\) 开头的序列的字典序一定比这个序列小,以 \(1\) 开头的序列一共有 \(4!\)

接下来我们发现,以 \(2\) 开头的序列的字典序不一定比它小,我们可以考虑第一位为 \(2\) ,第二位为小于 \(5\) 且不为 \(2\) 的排列

若如此构造,第二位共 \(3\) 种选择,剩下的三位有 \(3!\) 种可能,即第一位最大,剩下的 \(4\) 位共 \(3 \times 3!\) 种选择

同理,前两位最大,剩下的 \(3\) 位共 \(2!\) 种可能

前四位最大,剩下一位只有 \(1!\) 种可能

所以这个序列的排名是 \(1 + 1 \times 4! + 3 \times 3! + 1 \times 2! + 1 \times 1! = 46\)

枚举每一位是 \(O(n)\) ,找未确定的比第 \(i\) 位小的数是 \(O(n)\) ,总时间复杂度是 \(O(n^2)\)?

我们考虑优化,再找比第 \(i\) 位小的数时,我们可以用树状数组优化到 \(O(n \log n)\)

P5367 【模板】康托展开

#include 
typedef long long ll;
using namespace std;
const ll Mod=998244353;
const int N=1e6+7;

ll fac[N];
int a[N];
int c[N];

int n;
ll ans;

inline int lowbit(int x) {
	return x&((~x)+1);
}

inline void update(int pos,int val) {
	for(;pos<=n;pos+=lowbit(pos))
		c[pos]+=val;
}

inline int query(int pos) {
	int sum=0;
	for(;pos;pos-=lowbit(pos))
		sum+=c[pos];
	return sum;
}

signed main() {
	scanf("%d",&n);
	fac[0]=1;
	for(int i=1;i<=n;++i)
		fac[i]=fac[i-1]*i%Mod; // 预处理阶乘数组
	for(int i=1;i<=n;++i)
		scanf("%d",a+i);
	for(int i=1;i<=n;++i)
		update(i,1); // 树状数组维护
	for(int i=1;i<=n;++i) {
		ans=(ans+fac[n-i]*query(a[i]-1)%Mod)%Mod; // 统计答案
		update(a[i],-1); // 因为后面考虑的情况中 a[i] 没有贡献,删去
	}
	printf("%lld",ans+1);
    return 0;
}

扩展:逆康托展开

我们考虑这个问题

求长度为 \(5\) ,排名为 \(46\) 的序列是多少

排名为 \(46\) ,就意味着比这个序列小的序列有 \(45\)

考虑第一位,因为 \(\left[ \dfrac{46}{4!}\right] = 1\) ,所以当第一位为小于等于 \(1\) 的数时,后 \(4\) 为随便排,都比这个序列小,而当第一位为 \(2\) 时,后买你的书就有了限制,即当第一位为 \(2\) 时,第一位与这个序列的第一位相同,我们就可以确定第一位

接下来让排名减去 \(1 \times 4!\) 得到 \(21\) , 因为 \(\left[ \dfrac{21}{3!}\right] = 3\) ,且我们已经确定了第一位为 \(2\)\(2 \leq 3\),所以第二位就是剩下的数中第 \(3+1\)? 小的数 \(5\)

同理,让排名减去 \(3 \times 3!\)? 因为 \(\left[ \dfrac{3}{2!}\right] = 1\)? ,所以第三位就是剩下的数中第 \(1+1\)? 小的数 \(3\)??

让排名减去 \(1 \times 2!\)?? 因为 \(\left[ \dfrac{2}{1!}\right] = 1\)?? ,所以第四位就是剩下的数中第 \(1+1\)?? 小的数 \(4\)?

第五位就是剩下来的 \(1\)

所以排名为长度为 \(5\) ,排名为 \(46\) 的序列就是 \([2,5,3,4,1]\)?

至此,我们便完成了逆康托展开

一些例题:

P2524 Uim的情人节礼物·其之弐

P3014 [USACO11FEB]Cow Line S