首页 > 其他分享 >YTU 1712 排列的字典序问题

YTU 1712 排列的字典序问题

时间:2024-03-31 10:33:35浏览次数:18  
标签:1712 arr 排列 数列 int YTU 给定 我们 字典

题目描述

n个元素{1,2,……, n }有n!个不同的排列。将这n!个排列按字典序排列,并编号为0,1,…,n!-1。每个排列的编号为其字典序值。例如,当n=3时,6 个不同排列的字典序值如下: 


给定n以及n个元素{1,2,……, n }的一个排列,计算出这个排列的字典序值,以及按字典序排列的下一个排列。

输入

输入数据的第1行是元素个数n(n≤20)。接下来的1行是n个元素 {1,2,……, n }的一个排列。

输出

输出数据的第1行是字典序值,第2行是按字典序排列的下一个排列。

输入输出样例

样例输入 #1

复制

8
2 6 4 5 8 1 7 3
样例输出 #1

复制

8227
2 6 4 5 8 3 1 7

 

分析:

        对于该问题呢,主要难点有两个,一个是如何计算给定的数列是第几个,另一个就是计算它的下一位是多少。

        对于第一个问题呢,我们很容易想到dfs来全排列对吧,但是数据给到了20,如果你想要去算20个数的全排列可能会超时,所以我们只能在数学方面想办法优化。那么怎么写呢,我们可以看到这些全排列的数列是按照大小来排序的,那也是不是就是说只要我们求出比给定的这个数列小的数列有几个是不是就可以算出来了呢。OK,开始分析:

我们以样例给定的数列为例子  2 6 4 5 8 1 7 3,我们先看第一位,第一位是2,那么是不是所有以1开头的数都比2小啊,那以1开头的数有多少个呢,答案1:是1*7!;

好了我们看完了第一位是1,如果第一位是2,想得到比给定数列小的数是不是只能让第二位比给定的数列的数小啊,我们可以看到第二位数字是6,那么就是说第二位的数字可以是1,2,3,4,5但是我们的第一位这个时候已经是2了,(这是一个很重要的地方)所以第二位只能是1,3,4,5,OK我们可以得到答案2:4*6!;

同理我们看第三位数,前边两位数只能是2 6,给定的数列第三位是4,那么第三位是不是只能是1,2,3,同理因为前两位定住了是2,6那么第三位只能是1,3;得到答案3: 2*5!

......

最后吧答案n加起来即可

经过一顿分析,我们可以看出其中的规律,对给定的数列每一位数进行分析,答案就是在这个位置往后找有几个数比他小我们记作n,(为什么往后找比她小的数呢,因为在他前边的数都是已经定住了,如果再选用的话会重复)这个数往后有几个空位置我们看作m,那么其中一个答案就是n*m!;最后把所有的数加起来就是结果。

        对于第二个问题,如何求解下一个数列,说白了就是求一个比它大的数列s,而且s数列减去给定的数列的结果最小(就是比它大的最小数列);我们可以通过交换数列的位置来得到。分析一下,是不是我们要尽可能保证两个数列前边的数一样,越是往后的数不同,他们的差值是不是就越小,举个例子 ,对于 2 6 4 5 8 1 7 3 我们要交换的话,肯定是希望3和1交换而不是希望2和3交换,因为我们尽可能保证前边的高位数次序不变。那么怎么实现呢?

我们可以倒序遍历,在倒序的过程当中我们寻找这个数的后边有没有比他大的数,找到那个比它大的最少的交换位置。这样就OK了吗?nonono...我们还要把这个数往后所有的数从小到大再给他排序一遍,为啥呢?请看VCR:

        对于例子2 6 4 5 8 1 7 3 我们按着我们分析的来,

倒序查找,先找3,3后边有比他大的数吗?好像没有...

再往前找到了7,7后边有比他大的数吗?好像没有...

再找1,后边有比他大的数吗?有,7和3,那么到底要和谁换位呢?我们上边说了,要和比它大的最少的那个数换位,那肯定就是3了对吧,OK换就完了 2 6 4 5 8 3 7 1,这就完了?和答案不一样啊!对,我们还要把3后边所有的数给他排序一遍(可以借助sort)就得到了 2 6 4 5 8 3 1 7 !!

OK!上代码!

代码:

#include<iostream>
#include<algorithm>
using namespace std;
int n;
int arr[21],brr[21];
int ans = 0;

int main()
{
	cin >> n;
	brr[1] = 1;
	for (int i = 2; i <= n; i++)
		brr[i] = brr[i - 1] * i;//求出n个数的阶乘并记录
	for (int i = 1; i <= n; i++)
		cin >> arr[i];
	for (int i = 1; i <= n; i++)
	{
		int num=0;//记录对于该点,该点后边有多少个小于他的数
		for (int j = i + 1; j <= n; j++)
		{
			if (arr[j] < arr[i])
				num++;
		}
		ans += num * brr[n-i];
	}
	cout << ans << endl;
	int sign = 0,t=1e9,b;
	for (int i = n; i >= 1; i--)
	{
		for (int j = i + 1; j <= n; j++)
		{
			if (arr[j] > arr[i])//如果后边有大于标记点的数
			{
				if (arr[j] < t)//不断更新大于标记点的最小值
				{
					t = arr[j];
					b = j;//记录大于标记点的最小值的下标
				}
				sign = 1;
			}
		}
		if (sign == 1)//如果后边有大于标记点的数
		{
			int p;//标记点与最小的大于标记点的数换位
			p = arr[i];
			arr[i] = arr[b];
			arr[b] = p;
			sort(arr + i + 1, arr + 1 + n);//排序后边所有的书从小到大
			break;
		}
	}
	for (int i = 1; i <= n; i++)
		cout << arr[i] << ' ';
	return 0;
}

标签:1712,arr,排列,数列,int,YTU,给定,我们,字典
From: https://blog.csdn.net/2302_80282666/article/details/137192739

相关文章

  • P8306 【模板】字典树
    原题链接题解1.建议去B站上看看动画演示,你就明白怎么回事了2.如何用代码实现呢?看完你就明白了code#include<bits/stdc++.h>usingnamespacestd;intnum=0;inttree[3000006][75]={0};intcnt[3000006]={0};chars[3000006];intans;intt,n,q;//放全局变量是为了加......
  • 帝国CMS十合一源码/字典/成语/古诗词/二十四节气/英语单词/百家姓/范文文库/词语等
    帝国CMS十合一源码/字典/成语/古诗词/二十四节气/英语单词/百家姓/范文文库/词语等功能包含:成语大全二十四节气英语单词古诗词近反义词词语造句汉语字典英文缩写百家姓范文文库文件目录:1个数据库  1个系统源码  1个伪静态规则安装方式:把1.2G的程序上传到网......
  • python处理字典之表格-城市排行榜
    #中国城市排行榜importxlrdbook=xlrd.open_workbook('city_data.xls')sheet=book.sheet_by_index(0)main_data_list=[]forrowinrange(3,sheet.nrows):temp_dict={}#print(sheet.row_values(row))temp_dict["城市"]=sheet.row_values(row......
  • python 列表、元组、字典、集合的区别
    目录列表(List)元组(Tuple)字典(Dictionary)集合(Set)列表(List)有序:列表中的元素是有序的,可以通过索引访问。可变:你可以修改列表,比如添加、删除或改变元素。可重复:列表可以包含重复的元素。语法:使用方括号 [] 定义,元素用逗号分隔。应用场景:当你有一个元素......
  • day10:字典的循环遍历及序列操作
    一、字典的循环遍历1.遍历字典的键dict1={'name':'张三','age':20,'gender':'男'}forkeyindict1.keys():print(key)#name#age#gender2.遍历字典的值dict1={'name':'张三','age':20,'......
  • Python 字符串转为字典的两种常用方式(接口交互时)
    结论:在做接口时,请求、响应信息,必须要用json格式 原因:常规的字符串转为字典有两种方式,但两种方式都存在一定的问题:1、ast.literal_eval()(包含eval等类型方法)问题1:安全性,(literal_eval安全性好一些,eval不安全)问题2:需要将字符串中的 true false  null  =》 True......
  • python-列表、元组、字符串、集合、字典等用法
    目录1.列表(list)1.1  列表的定义语法1.2  列表的下标索引1.3  列表的常用操作1.4  列表的循环遍历示例2.元组(tuple)3.字符串4.数据容器(序列)的切片4.2序列切片课后练习5.集合(set)5.1  集合的操作方法6.字典(dict)7.容器排序,排序之后会变成列表对象1.......
  • 【Python系列】Python 中 YAML 文件与字典合并的实用技巧
    ......
  • 洛谷 P8306 【模板】字典树
    写模板:1确定树的节点指针数量2确定起始字符3实现插入方法4根据题目编写求解方法,或者添加计数元素到节点中structNode{array<int,100>next{};intcnt=0;};classTrie{public:Trie(charstart):start_(start),root_(0){trie_.resize(1)......
  • 字典
    概述用键值对的方式存储数据基础使用dic={"name":"张三","age":20,"score":88}#查看变量的类型print(type(dic))#获取字典中的值n=dic["name"]print(n)#向字典中添加值,如果存在,就是修改dic["身高"]=180print(dic)#设置默认值,向字典中添加值,如......