洛谷 P1338 末日的传说

4 篇文章 0 订阅

题目描述

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

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

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

1, 2, 3, … N

第二天,日历自动变为

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

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

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

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

输入输出格式

输入格式:

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

输出格式:

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

输入输出样例

输入样例#1:
5 4
输出样例#1:
1 3 5 4 2

说明

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

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

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

所有数据均有解。



很明显,可以发现每次的数串只交换了两个数字,再次看会发现交换的两个数的位置有规律。
嗯,那就需要优化了,然后就发现每隔 1 3 6 10 15 21 28...(就是S=1+...N)的数串,正好都是把尾末的一段数字倒转而已
  • x=1 123 54

  • x=1+2=3 12 543

  • x=1+2+3=6 1 5432
转载自—— 洛谷题解

#include<algorithm>
#include<iostream>
#include<cstdio>
using namespace std;
int n,m,a[50005];
void print()
{
	for(int i=1;i<=n;i++)
		printf("%d ",a[i]);
	printf("\n");
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
		a[i]=i;
	if(m==0)
	{
		print();
		return 0;
	}
	int x=0,y=0;
	while(m-y>=0)
		++y,m-=y;
	for(int i=n;i>=n-y;i--)
		a[i]=2*n-i-y;
	y=n-y-1;
	x=n;
	for(int i=1;i<=m;i++)
	{
		swap(a[x],a[y]);
		if(x-y<=1)
			x=n,y--;
		else
			x--;
	}
	print();
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值