Codeforces 513B Permutations

You are given a permutation p of numbers 1, 2, ..., n. Let's define f(p) as the following sum:

Find the lexicographically m-th permutation of length n in the set of permutations having the maximum possible value of f(p).

Input

The single line of input contains two integers n and m (1 ≤ m ≤ cntn), where cntn is the number of permutations of length n with maximum possible value of f(p).

The problem consists of two subproblems. The subproblems have different constraints on the input. You will get some score for the correct submission of the subproblem. The description of the subproblems follows.

  • In subproblem B1 (3 points), the constraint 1 ≤ n ≤ 8 will hold.
  • In subproblem B2 (4 points), the constraint 1 ≤ n ≤ 50 will hold.
Output

Output n number forming the required permutation.

Sample test(s)
input
2 2
output
2 1 
input
3 2
output
1 3 2 
Note

In the first example, both permutations of numbers {1, 2} yield maximum possible f(p) which is equal to 4. Among them, (2, 1) comes second in lexicographical order.

解题思路:本题要求解的是字典序第m大的最优解的方案。首先对于最优方案我们是这样得到的,首先对于1我们应该放置其在位置1或者位置n处,因为如果将1放置在数组的中间则会有更多的(i,j)满足min(i,j)=1,这样肯定比当前方案差,因此1应该放置位置1或者位置n处,存在两种选择。当然对于2应该放置在剩余空位置处的左右两端的其中一个位置,这样依此类推进行放置,最终得到的序列结果肯定是最优的,且这样的序列的个数为2^(n-1)。现在我们要求解字典序第m大的排列方案,首先对于1放置在位置1处对应前2^(n-2)种方案,放置在n处也对应后2^(n-2),这样我们不难想到采用二进制分解的方法来求解第m大的方案。

#include <ctime>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <map>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 110;
int arr[maxn];

int main() {

    int n;
    ll  m;
    int p1, p2;
    cin >> n >> m;
    p1 = 1;
    p2 = n;
    m--;
    for(int i = n-2, j = 1; i >= 0; --i, ++j) {
        if(m&(1LL<<i)) {
            arr[p2] = j;
            p2--;
        } else {
            arr[p1] = j;
            p1++;
        }
    }
    arr[p1] = n;
    for(int i = 1; i <= n; ++i) {
        if(i == 1) {
            printf("%d", arr[i]);
        } else {
            printf(" %d", arr[i]);
        }
    }
    printf("\n");
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值