9 条题解

  • 47
    @ 2023-7-28 12:10:09

    P1017

    -题目回顾-

    人类终于登上了火星的土地并且见到了神秘的火星人。人类和火星人都无法理解对方的语言,但是我们的科学家发明了一种用数字交流的方法。这种交流方法是这样的,首先,火星人把一个非常大的数字告诉人类科学家,科学家破解这个数字的含义后,再把一个很小的数字加到这个大数上面,把结果告诉火星人,作为人类的回答。

    火星人用一种非常简单的方式来表示数字――掰手指。火星人只有一只手,但这只手上有成千上万的手指,这些手指排成一列,分别编号为 1,2,3,。火星人的任意两根手指都能随意交换位置,他们就是通过这方法计数的。

    一个火星人用一个人类的手演示了如何用手指计数。如果把五根手指――拇指、食指、中指、无名指和小指分别编号为1,2,3,45,当它们按正常顺序排列时,形成了 5 位数 12345,当你交换无名指和小指的位置时,会形成 5 位数 12354,当你把五个手指的顺序完全颠倒时,会形成 54321,在所有能够形成的1205 位数中,12345 最小,它表示 112354 第二小,它表示 254321 最大,它表示 120


    -分析-

    输出n个数全排列的第x个排列


    -代码-

    #include <bits/stdc++.h>
    using namespace std;
    int main()//by AGOMG
    {
        int n, num[10005], x;
        cin >> n >> x;
        for (int i = 1; i <= n; i++)
            cin >> num[i];
        for(int i = 1; i <= x; i++)
            next_permutation(num + 1, num + n + 1);
        for(int i = 1; i <= n; i++)
            cout << num[i] << ' ';
        return 0;
    }
    
    
  • 9
    @ 2024-3-30 11:43:21

    这道题其实很简单,但是题目十分难懂。我们先看原题的描述:

    人类终于登上了火星的土地并且见到了神秘的火星人。人类和火星人都无法理解对方的语言,但是我们的科学家发明了一种用数字交流的方法。这种交流方法是这样的,首先,火星人把一个非常大的数字告诉人类科学家,科学家破解这个数字的含义后,再把一个很小的数字加到这个大数上面,把结果告诉火星人,作为人类的回答。

    火星人用一种非常简单的方式来表示数字――掰手指。火星人只有一只手,但这只手上有成千上万的手指,这些手指排成一列,分别编号为 ​1​,​2,​3​,​⋯​。火星人的任意两根手指都能随意交换位置,他们就是通过这方法计数的。

    一个火星人用一个人类的手演示了如何用手指计数。如果把五根手指――拇指、食指、中指、无名指和小指分别编号为​1​,​2,3​,4和5,当它们按正常顺序排列时,形成了5位数12345,当你交换无名指和小指的位置时,会形成5位数12354​,当你把五个手指的顺序完全颠倒时,会形成 ​54321​,在所有能够形成的120个5位数中,12345 最小,它表示1​;12354第二小,它表示 ​2​;54321最大,它表示 ​120。

    我来概括一下: 大意就是让你用next_permutation()对火星人的手指排列顺序进行更改,更改顺序为科学家给的那个小整数。

    —————————————————————AC代码—————————————————————

    #include <bits/stdc++.h>
    using namespace std;
    int n,a,num[10086];//定义变量和数组
    int main(){
        cin>>n>>a;//输入火星人手指的个数和加上去的整数
        for (int i=1;i<=n;i++){
        cin>>num[i];//输入火星人手指的排列顺序
        }
        for(int i=1;i<=a;i++){
            next_permutation(num+1,num+n+1);//使用next_permutation()改变手指的排列顺序,循环a次
        }
        for(int i=1;i<=n;i++){
            cout<<num[i]<<" ";//依次输出
        }
        return 0;
    }
    

    编写题解不易,点个赞再把题解抱走吧!

  • 8
    @ 2023-8-9 19:42:56

    哈!劳资来搞事情喽!代码+时间(本以为会超时,结果生生O(n + m)😕 )

    # 状态分数 耗时 内存占用
    #1 Accepted10 1ms 376 KiB
    #2 2ms 504 KiB
    #3 1ms 376 KiB
    #4
    #5 2ms
    #6
    #7
    #8
    #9 1ms
    #10 2ms 504 KiB

    代码

    下载

    #include <bits/stdc++.h>
    using namespace std;
    int main()
    {
        int a[10005],m,n;
        cin >> n >> m;
        for (int i = 1;i <= n;i++) cin >> a[i];
        for (int i = 1;i <= m;i++) next_permutation(a + 1,a + n + 1);
        for (int i = 1;i <= n;i++) cout << a[i] << " ";
    }
    
  • 4
    @ 2023-8-9 20:18:28
    #include <iostream>
    #include <algorithm>
    using namespace std;
    int main(){
        ios::sync_with_stdio(false);
        cin.tie(NULL);
        cout.tie(NULL);
        int n,m,a[10005];
        cin>>n>>m;
        for(int i=1;i<=n;i++)cin>>a[i];
        for(int i=1;i<=m;i++)next_permutation(a+1,a+n+1);
        for(int i=1;i<=n;i++)cout<<a[i]<<' ';
        return 0;
    }
    

    因为是先变换,整体应该是whlle而不是do_while形式

  • 3
    @ 2024-6-14 22:49:59

    P1017

    题目回顾

    对方的语言,但是我们的科学家发明了一种用数字交流的方法。这种交流方法是这样的,首先,火星人把一个非常大的数字告诉人类科学家,科学家破解这个数字的含义后,再把一个很小的数字加到这个大数上面,把结果告诉火星人,作为人类的回答。

    火星人用一种非常简单的方式来表示数字――掰手指。火星人只有一只手,但这只手上有成千上万的手指,这些手指排成一列,分别编号为 ​1​,​2​,​3​,​​。火星人的任意两根手指都能随意交换位置,他们就是通过这方法计数的。

    一个火星人用一个人类的手演示了如何用手指计数。如果把五根手指――拇指、食指、中指、无名指和小指分别编号为​1​,​2​,​3​,4 和 ​5​,当它们按正常顺序排列时,形成了 5 位数 ​12345​,当你交换无名指和小指的位置时,会形成 5 位数 ​12354​,当你把五个手指的顺序完全颠倒时,会形成 ​54321​,在所有能够形成的1205 位数中,12345 最小,它表示 ​1​;12354 第二小,它表示 ​2​;54321 最大,它表示 ​120​。

    分析

    这道题可以直接这样:

    #include <bits/stdc++.h>
    using namespace std;
    int n,m,num[10005];
    int main()
    {
        cin>>n>>m;
        for(int i=1;i<=n;i++){
            cin>>num[i];
        }
        do
        {
            m--;
        }while(next_permutation(num+(n-6),num+n+1)&&m);
        for(int i=1;i<=n;i++){
            cout<<num[i]<<" ";
        }
        return 0;
    }
    

    其实也可以不这么复杂:

    #include <bits/stdc++.h>
    using namespace std;
    int n,m,num[10005];
    int main()
    {
        cin>>n>>m;
        for(int i=1;i<=n;i++){
            cin>>num[i];
        }
        do
        {
            m--;
        }while(next_permutation(num+1,num+n+1)&&m);
        for(int i=1;i<=n;i++){
            cout<<num[i]<<" ";
        }
        return 0;
    }
    

    这样即可。

    • 2
      @ 2024-1-6 17:37:56
      #include <iostream>
      #include <algorithm>
      using namespace std;
      int num[10005];
      int main()
      {
          int n, m;
          cin >> n >> m;
          for (int i = 1; i <= n; ++i)
              cin >> num[i];
          for (int i = 1; i <= m; ++i)
              next_permutation(num + 1, num + n + 1);
          for (int i = 1; i < n; ++i)
              cout << num[i] << ' ';
          cout << num[n];
      }
      
      • 2
        @ 2023-4-8 19:24:10
        #include <iostream>
        #include <algorithm>
        using namespace std;
        int num[10005];
        int main()
        {
            int n, m;
            cin >> n >> m;
            for (int i = 1; i <= n; ++i)
                cin >> num[i];
            for (int i = 1; i <= m; ++i)
                next_permutation(num + 1, num + n + 1);
            for (int i = 1; i < n; ++i)
                cout << num[i] << ' ';
            cout << num[n];
        }
        
        • 0
          @ 2023-4-8 16:32:06

          思路:

          对于1~n的全排列,找到一个给定排列后的第m个排列。

          对于当前序列重复执行m次next_permutation。

          #include <iostream>
          #include <algorithm>
          using namespace std;
          int num[10005];
          int main()
          {
              int n, m;
              cin >> n >> m;
              for (int i = 1; i <= n; ++i)//输入n个整数的排列顺序
                  cin >> num[i];
              //输入后对应num就像是题目中三进制数的最小值1,接下来如果m是5,那最后是加成6,对应外星人手指排列应该是321,输出321就行
              //123变到321是通过全排列5次得到,所以本题可以总结为以下:
              //对于当前序列重复执行m次next_permutation。
              for (int i = 1; i <= m; ++i)
                  next_permutation(num + 1, num + n + 1);
              //输出第m次序列中的数
              for (int i = 1; i < n; ++i)
                  cout << num[i] << ' ';
              cout << num[n];
          }
          
          
          • -20
            @ 2023-4-6 17:39:15
            题目大意
                    对于1~n的全排列,找到一个给定排列后的第m个排列。

            完整思路
                    对于当前序列重复执行m次next_permutation。

            核心代码
            
            
          • 1

          信息

          ID
          3
          时间
          1000ms
          内存
          256MiB
          难度
          3
          标签
          递交数
          2166
          已通过
          1201
          上传者