zoukankan      html  css  js  c++  java
  • 排序工作量之新任务(SHOI2001)

    排序工作量之新任务(SHOI2001)

    给出两个整数n和t,求n的全排列中逆序对数为t的个数,和逆序对数为t的字典序最小全排列。

    首先第一个问题可以用dp解决,(f[i][j])表示前i个数,j个逆序对的序列数,那么(f[i][j]=f[i-1][j-k] (k<i)(kle j))

    易证明一个全排列,交换值差1的两个数,逆序对个数+或-1。同时可以推出逆序对数为t时的字典序最小全排列,一定一个严格上升,公差为1的序列,后面接上两个严格下降,公差为1的序列,并且后面两个序列衔接处差2。因此从后往前处理,不停交换当前数与后面的一个数即可。具体怎么实现请看代码。

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    
    const int maxn=25;
    int n, t;
    long long f[maxn][maxn*maxn];
    int a[maxn];
    
    int main(){
    	scanf("%d%d", &n, &t);
    	if (t==0){
    		puts("1");
    		for (int i=1; i<=n; ++i) printf("%d ", i);
    		return 0; }
    	f[1][0]=f[2][0]=f[2][1]=1;
    	for (int i=3; i<=n; ++i)
    		for (int j=0; j<=i*(i-1)/2; ++j)
    			for (int k=0; k<i&&k<=j; ++k)
    			f[i][j]+=f[i-1][j-k];
    	printf("%lld
    ", f[n][t]);
    	for (int i=1; i<=n; ++i) a[i]=i;
    	for (int i=n-1; i>=1; --i){
    		for (int j=n; j>i; --j){
    			swap(a[i], a[j]);
    			if (!(--t)) break;
    		} if (!t) break;
    	}
    	for (int i=1; i<=n; ++i) printf("%d ", a[i]);
    	return 0;
    }
    
  • 相关阅读:
    sqoop导出数据
    sqoop导入数据
    Hive学习(二)
    各个版本的集群安装包地址
    Hive学习(一)
    数据仓库
    HBase学习(二)
    HBase学习(一)
    MySQL中阻塞
    MySQL中锁问题
  • 原文地址:https://www.cnblogs.com/MyNameIsPc/p/9010988.html
Copyright © 2011-2022 走看看