• [洛谷P1338] 末日的传说


    洛谷题目链接:末日的传说

    题目描述

    只要是参加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。

    所有数据均有解。

    一句话题意: 求一个长度为(n),元素为(1)~(n)逆序数为(m)的一个排列, 使得这个排列在全排列中的位置最小.

    题解: 首先我们可以确定一个贪心的思想,也就是越前面的数字要越小.

    然后我们再来考虑如何计算这个逆序的问题.

    为了让一个数产生的逆序最大,可以将它放到最后面.

    这样如果按照(1)~(n)的顺序枚举过来,现在要将第一个数放到一个位置,显然如果放在最后一位,1所能产生的逆序数就是(n-1),如果放在最前面,就能保证答案一定是最优的.

    假设前面的数放到了第(h)位,要放到后面的数放到了第(t)位,那么这样得到的逆序数就是(t-h+1).

    那么可以直接这样贪心模拟,算出每一个数字插入哪一位.

    最后要记得开long long.

    #include<bits/stdc++.h>
    using namespace std;
    const int N=50000+5;
    typedef long long lol;
    
    lol n, m, a[N];
    
    int main(){
        cin >> n >> m; lol h = 0, t = n+1;
        for(lol i=1;i<=n;i++){
    	    lol temp = (n-i)*(n-i-1)/2;
    	    if(temp >= m) a[++h] = i;
    	    else a[--t] = i, m -= t-h-1;
        }
        for(lol i=1;i<=n;i++) printf("%lld ",a[i]);
        printf("
    ");
        return 0;
    }
    
  • 相关阅读:
    Linux 安装 iptables防火墙
    CentOS最常用命令及快捷键整理
    WebAPI 和 webservice接口
    Linux 文件权限
    Linux查看系统信息的一些命令及查看已安装软件包的命令
    navicat连接虚拟机(centos)中的mysql
    Nmap扫描与Tcpdump抓包分析
    python 识别验证码自动登陆
    iptables开通某些端口
    hive的安装和使用
  • 原文地址:https://www.cnblogs.com/BCOI/p/9040786.html
Copyright © 2020-2023  润新知