康托展开学习笔记


什么是康托展开

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

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

如何康托展开

我们看这样一个序列 \([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