[洛谷P1088]火星人

思路:

全排列。

为什么要用全排列?

因为火星人如果有\(1\)个手指头 那只能表示一个数字了。
火星人如果有两个手指头,那么显然有\(12\)\(21\)两种表示
火星人如果有三个手指头,那么第三个手指头可以放在前两个手指头的左边 中间、或者右边,也就是说不管前两个手指头是\(12\) 还是\(21\),第三个手指头都有3种放法,那么一共就是\(2*3=6=3!\)种了……
如果火星人的前\(k-1\)个手指头有\((k-1)!\)种排列方式,那么不论前\(k-1\)个手指头如何排列,多的一个手指头可以放到最前面,或者是任意一个已知手指头的后面,也就是\(1+k-1=k\)种。那么\(k\)个手指头就有\(k!\)种排列了。
数学归纳,说明了\(n\)个手指头 就是\(n!\)个方法
但是题目所给的\(N\)特别大,而且排列为随机给定,所以用朴素的递归求排列只能通过一小部分数据。但是观察后发现要加上去的\(M\)很小,所以转而求给定排列的后\(m\)个排列...

STL有一个全排列函数,在此把这位大佬介绍的给大家看看:传送门

Code

#include<cstdio>
#include<algorithm>

using namespace std;
const int maxn = 10000+5;
int num[maxn];

int main()
{
    int n,m;
    while( scanf("%d%d",&n,&m) == 2)
    {
        for( int i = 0; i < n; i++)
            scanf("%d",&num[i]);

        for( int i = 0; i < m; i++)
            next_permutation(num,num+n);  //求全排列

        for( int i = 0; i < n; i++)
            printf(i==n-1?"%d\n":"%d ",num[i]);

    }

    return 0;
}

猜你喜欢

转载自www.cnblogs.com/lyfoi/p/9191612.html
今日推荐