题解:P6635 「JYLOI Round 1」箭头调度

本蒟蒻来 一篇题解

看到字典序排列,很容易联想到康托展开,那么可能有小蒟蒻要问:什么是康托展开?

康托展开是将n!-1的整数表达式写成 $ a[n−1] \times (n − 1)!+a[n − 2] \times (n − 2)!+...+a[2] \times 2!+a[1] \times 1! $ 的形式,那么排列字符中第k小的字典序就是将k-1利用康托展开后每一位中没有被放置东西过的第a[n-1]的字符。

进行康托展开后就可以利用我们所得到的第k小的字符的排列
再利用下标来求出拓补排序的序列就可以啦,如果当前序列是从前向后☞的,那就可以输出0,否则就说明需要翻转,就输出1。

当然,上面是一种比较标准的做法,想要打点**骗分**运用人类智慧的,请向下看。

测试点一:啥也不输出就可以骗到10分

测试点二:直接枚举找字符,但是复杂度有点超,慎用

测试点三:字典序中第 k 小的拓扑序便是 n 的全排列中字典序第 k小的那个序列啦。

证明比较麻烦,可以参考第一篇题解的大佬,本蒟蒻还没有那个实力:(

测试点四:只要对于上面的结论进行一遍暴力然后连边就可以啦,

#include<bits/stdc++.h>
using namespace std;
int n,m,k,a[10005],b[10005];
int main() {
	cin>>n>>m>>k;
	for(int i=1;i<=n;i++){
		a[i]=i;
	}
	for(int i=1;i<=k-1;i++){
		next_permutation(a+1,a+n+1);
	}
	for(int i=1;i<=n;i++){
		b[a[i]]=i;
	}
	for(int i=1;i<=m;i++){
		int u,v;
		cin>>u>>v;
		cout<<(b[u]>b[v]);
	}
	return 0;
}
posted @ 2025-08-11 15:21  Rookie青果  阅读(4)  评论(0)    收藏  举报