zoukankan      html  css  js  c++  java
  • 2021寒假每日一题《火星人》

    火星人

    题目来源:NOIP2004普及组
    时间限制:(1000ms) 内存限制:(128mb)

    题目描述

    人类终于登上了火星的土地并且见到了神秘的火星人。
    人类和火星人都无法理解对方的语言,但是我们的科学家发明了一种用数字交流的方法。
    这种交流方法是这样的,首先,火星人把一个非常大的数字告诉人类科学家,科学家破解这个数字的含义后,再把一个很小的数字加到这个大数上面,把结果告诉火星人,作为人类的回答。
    火星人用一种非常简单的方式来表示数字——掰手指。
    火星人只有一只手,但这只手上有成千上万的手指,这些手指排成一列,分别编号为 (1, 2, 3, …)
    火星人的任意两根手指都能随意交换位置,他们就是通过这方法计数的。
    一个火星人用一个人类的手演示了如何用手指计数。
    如果把五根手指——拇指、食指、中指、无名指和小指分别编号为 (1) , (2) , (3) , (4)(5) ,当它们按正常顺序排列时,形成了5位数 (12345) ,当你交换无名指和小指的位置时,会形成5位数 (12354) ,当你把五个手指的顺序完全颠倒时,会形成 (54321) ,在所有能够形成的120个5位数中, (12345) 最小,它表示 (1)(12354) 第二小,它表示 (2)(54321) 最大,它表示 (120)
    下表展示了只有3根手指时能够形成的 (6)个3位数和它们代表的数字:
    三位数 ([123, 132, 213, 231, 312, 321])
    分别代表的数字 ([1, 2, 3, 4, 5, 6])
    现在你有幸成为了第一个和火星人交流的地球人。
    一个火星人会让你看他的手指,科学家会告诉你要加上去的很小的数。
    你的任务是,把火星人用手指表示的数与科学家告诉你的数相加,并根据相加的结果改变火星人手指的排列顺序。
    输入数据保证这个结果不会超出火星人手指能表示的范围。

    输入格式

    输入包括三行,第一行有一个正整数 (N) ,表示火星人手指的数目。
    第二行是一个正整数 (M) ,表示要加上去的小整数。
    下一行是有 (N) 个整数的一个排列,用空格隔开,表示火星人手指的排列顺序。

    输出格式

    输出只有一行,这一行含有 (N) 个整数,表示改变后的火星人手指的排列顺序。
    每两个相邻的数中间用一个空格分开,不能有多余的空格。

    数据范围

    (1 ≤ N ≤ 10000) ,
    (1 ≤ M ≤ 100)

    样例输入

    5
    3
    1 2 3 4 5
    

    样例输出

    1 2 4 5 3
    

    解题思路

    按照题目给的 (3) 个手指的方案,发现顺序为字典序全排列,由字典序从小到大排列,第几个序列表示数字几。
    原始序列代表的数加上m,可以解释为,原始序列之后的第m个比它大的序列。

    在c++中,模板库里已经为我们写好了求字典序+1的函数,next_permutation(),只需要调用m次这个函数,就可以得到答案。

    java中没有此函数,所以需要手动写。

    解题代码-C++

    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    int main()
    {
        int n, m;
        cin >> n >> m;
        int *a = new int[n];
        for(int i = 0; i < n; i++)
        {
            cin >> a[i];
        }
    
        while(m--)
        {
            next_permutation(a, a + n);
        }
    
        for(int i = 0; i < n; i++)
        {
            cout << a[i] << ' ';
        }
        return 0;
    }
    

    解题代码-Java

    import java.util.*;
    
    public class Main {
        public static void main(String[] args) {
            Scanner input = new Scanner(System.in);
            int n = input.nextInt();
            int m = input.nextInt();
            int[] a = new int[n];
            for (int i = 0; i < n; i++) {
                a[i] = input.nextInt();
            }
            input.close();
            //C++STL库algorithm中使用next_permutation(a,a+n)可以得到比原序列字典序大1的序列
            //while (m--) {
            //    next_permutation(a,a+n);
            //}
            while (m > 0) {
                int k = n - 2;
                while (a[k] > a[k + 1]) {
                    k--;
                }
                int t = k + 1;
                while (t + 1 < n && a[t + 1] > a[k]) {
                    t++;
                }
                int temp = a[t];  //交换a[k]与a[t]的值,swap(a[k], a[t])
                a[t] = a[k];
                a[k] = temp;
                int left = k + 1, right = n - 1;
                while (left < right) {  //反转序列从k+1到n-1的项,reverse(a + k + 1, n)
                    temp = a[left];
                    a[left] = a[right];
                    a[right] = temp;
                    left++;
                    right--;
                }
                m--;
            }
            for (int i = 0; i < n; i++) {
                System.out.printf("%d ", a[i]);
            }
        }
    }
    
  • 相关阅读:
    HDU5418.Victor and World(状压DP)
    POJ2686 Traveling by Stagecoach(状压DP)
    POJ3254Corn Fields(状压DP)
    HDU5407.CRB and Candies(数论)
    CodeForces 352D. Jeff and Furik
    CodeForces 352C. Jeff and Rounding(贪心)
    LightOj 1282 Leading and Trailing
    Ural 1057. Amount of Degrees(数位DP)
    HDU 2089 不要62 (数位DP)
    HDU5366 The mook jong (DP)
  • 原文地址:https://www.cnblogs.com/hurentian/p/14337803.html
Copyright © 2011-2022 走看看