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;
    }
    
  • 相关阅读:
    Photon3Unity3D.dll 解析三——OperationRequest、OperationResponse
    关于VS2010的一些操作
    Photon3Unity3D.dll 解析二——EventData
    Photon3Unity3D.dll 解析一
    关于U3D中的移动和旋转
    U3D的一些常用基础脚本
    U3D模拟仿真实现
    构建基于TCP的应用层通信模型
    TCP协议的三次握手
    Python生成随机字符串
  • 原文地址:https://www.cnblogs.com/MyNameIsPc/p/9010988.html
Copyright © 2011-2022 走看看