codeforces 513 B2. Permutations

513 B2. Permutations

题意

定义
在这里插入图片描述
p为1 - n的排序
给定n和m,求使得f§ 的值最大的按照字典序排序的第m个排列

思路

关键在于使得f§值最大的排列一定是当前剩余数的最小放在排列的首部或者尾部

如果当前的剩余数的最小值不是在首或者尾,必然可以通过将该数移动到首或者尾使得f(x)的值更大

所以每次只需要判断将最小的数放在头还是尾即可

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class B2_513 {

    private static int N = 55;

    private int n;
    private long m;
    private int[] res = new int[N];
    private boolean[] st = new boolean[N];
    private long[] f = new long[N];

    public static void main(String[] args) throws IOException {
        B2_513 b2_513 = new B2_513();
        b2_513.read();
        b2_513.solve();
    }

    /**
     * f(p) = sum(min(p[i] --- p[j])) i -> (1, n), j -> (i, n)
     *
     * example:p = {1, 2}
     * i = 1, j = 1  min(p[1]) = 1
     * i = 1, j = 2  min(p[1], p[2]) = 1
     * i = 2, j = 2  min(p[2]) = 2
     * f(p) = 4
     *
     * p = {1, 2, 3}
     * i = 1, j = 1 min(p[1]) = 1
     * i = 1, j = 2 min(p[1], p[2]) = 1
     * i = 1, j = 3 min(p[1], p[2]) = 1
     * i = 2, j = 2 min(p[2]) = 2
     * i = 2, j = 3 min(p[2], p[3]) = 2
     * i = 3, j = 3 min(p[3]) = 3
     * f(p) = 10
     *
     */
    private void solve() {
        f[0] = 1L;
        f[1] = 1L;
        for(int i = 2; i <= n; i++) {
            f[i] = f[i - 1] * 2L;
        }
        dfs(1, n, n, m);
        for(int i = 1; i <= n; i++) {
            System.out.print(res[i] + " ");
        }
        System.out.println();
    }

    /**
     *
     * @param start  区间的左边
     * @param end   区间的右边
     * @param n  长度为n的序列
     * @param m  前m个序列
     */
    private void dfs(int start, int end, int n, long m) {
        if(start == end) {
            res[start] = n;
            return ;
        }
        // x: 当前要填入的值
        int x = n - (end - start);
        if(f[n - x] >= m) {
            // 添加在开头
            res[start++] = x;
            dfs(start, end, n, m);
        } else  {
            // 添加在结尾
            res[end--] = x;
            dfs(start, end, n, m - f[n - x]);
        }
    }

    private void read() throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String[] s = br.readLine().split(" ");
        n = Integer.parseInt(s[0]);
        m = Long.parseLong(s[1]);
    }
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值