【简单数学】末日的传说

【简单数学】末日的传说

题目

题目描述

只要是参加jsoi活动的同学一定都听说过Hanoi塔的传说:三根柱子上的金片每天被移动一次,当所有的金片都被移完之后,世界末日也就随之降临了。

在古老东方的幻想乡,人们都采用一种奇特的方式记录日期:他们用一些特殊的符号来表示从1开始的连续整数,1表示最小而N表示最大。创世纪的第一天,日历就被赋予了生命,它自动地开始计数,就像排列不断地增加。

我们用1-N来表示日历的元素,第一天日历就是

1, 2, 3, … N

第二天,日历自动变为

1, 2, 3, … N, N-1

……每次它都生成一个以前未出现过的“最小”的排列——把它转为N+1进制后数的数值最小。

日子一天一天地过着。有一天,一位预言者出现了——他预言道,当这个日历到达某个上帝安排的时刻,这个世界就会崩溃……他还预言到,假如某一个日期的逆序达到一个值M的时候,世界末日就要降临。

什么是逆序?日历中的两个不同符号,假如排在前面的那个比排在后面的那个更大,就是一个逆序,一个日期的逆序总数达到M后,末日就要降临,人们都期待一个贤者,能够预见那一天,到底将在什么时候到来?

输入格式

只包含一行两个正整数,分别为N和M。

扫描二维码关注公众号,回复: 10482748 查看本文章

输出格式

输出一行,为世界末日的日期,每个数字之间用一个空格隔开。

输入输出样例

输入 #1 复制
5 4
输出 #1 复制
1 3 5 4 2

说明/提示

对于10%的数据有N <= 10。

对于40%的数据有N <= 1000。

对于100%的数据有 N <= 50000。

所有数据均有解。

分析

前天才做过道逆序排序的,看这个题立马做,结果全错,问题完全不一样,,,,,,,,,,呃呃呃
然后重新看了题,嗯,不会。。。。。。。难受

题目:要求当逆序达到一个值M的时候,世界末日就要降临。(瑟瑟发抖)。
什么是逆序:排在前面的那个比排在后面的那个更大,就是一个逆序。

这个题,需要一个一个数看,比如: 开始是 1,2,3,4,5,(样例)
那么当排成 5,4,3,2,1 逆序最多,有 (4+1)*4 /2 个,*用到公式(n-1)n /2(这里很好理解吧)

1…题目 要求出最小的那么排序。。
先看第一个数,1,如果 1在排在最后,那么最多就有 (4+1)* 4 /2 个逆序,这时候我们先放在一边,
看第二个数,2,(这时有数,2,3,4,5) 如果 2在最后,最多就有 (3+1)*3 /2 ==6个,6个大于
要求到达逆序数m=4(样例), 这样的情况就是说 不管你 1放在前面还是后面,我不需要1也能排出
逆序数m=4 的序列, 那么好极了,我们把1放在前面,(因为题目要排序最小)。。。
后面的推论都是一样,看当前数 的后一个数 ,它的最大逆序数是否大于m,如果大于,就放在前面,

2…如果小于呢? 如果小于,那就把数放在最后面,然后看有多少个逆序对,m减掉。(只看前面数对这一位数)
(比如2放在最后面,这时1放在最前, 在2前面比他大的有3,4,5,三个,那么逆序数为3,)

3… 我们开个数组来存放,前面都放数组前面,后面放数组后面,最后顺序输出数组就好了。

是不是太啰嗦了,,,,,,,还不是为了写清楚,(又啰嗦了哈。。。。。)

代码

#include<iostream>

using namespace std;

long long  n,m;
int a[50005];
				
int main(){
	cin>>n>>m;
	int s=1,t=n;
	for(int  i=1;i<=n;i++){
		long long maxi = (n-i)*(n-i-1) /2;
		if(maxi >=m){
			a[s] = i;
			s++;
		}else{
			a[t] = i;
			t--;
			 m -= n-i; 
		}
	}
	for(int i=1;i<=n-1;i++){
		cout<<a[i]<<" ";
	}
	cout<<a[n]<<endl;
	return 0;
}
发布了75 篇原创文章 · 获赞 1 · 访问量 3642

猜你喜欢

转载自blog.csdn.net/A793488316/article/details/104666588