首页 > 试题广场 >

多多的电子字典

[编程题]多多的电子字典
  • 热度指数:3098 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
多多鸡打算造一本自己的电子字典,里面的所有单词都只由a和b组成。
每个单词的组成里a的数量不能超过N个且b的数量不能超过M个。
多多鸡的幸运数字是K,它打算把所有满足条件的单词里的字典序第K小的单词找出来,作为字典的封面。

输入描述:
共一行,三个整数N, M, K。(0 < N, M < 50, 0 < K < 1,000,000,000,000,000)


输出描述:
共一行,为字典序第K小的单词。
示例1

输入

2 1 4

输出

ab

说明

满足条件的单词里,按照字典序从小到大排列的结果是
a
aa
aab
ab
aba
b
ba
baa

备注:
对于40%的数据:0 < K < 100,000

对于100%的数据:0 < K < 1,000,000,000,000,000

题目保证第K小的单词一定存在
import java.util.Scanner;
import java.util.Arrays;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    static int n, m;
    static long k;
    static StringBuffer path = new StringBuffer();
    static long [][] dist = new long [55][55];

    static void dfs(int da, int db) {
        if (dist[n - da][m - db] != -1) {
            if (k - dist[n-da][m-db] > 0) {
                k -= dist[n-da][m-db];
                return;
            }
        }

        long cnt = k;
        k --;
        if (k == 0) {
            System.out.println(path);
            return;
        }
        if (k < 0) return;

        if (da < n) {
            path.append("a");
            dfs(da + 1, db);
            path.deleteCharAt(da + db);
        }
        if (db < m) {
            path.append("b");
            dfs(da, db + 1);
            path.deleteCharAt(da + db);
        }
        cnt -= k;   // 统计子节点个数(包括自身)
        dist[n-da][m-db] = cnt;
    }

    static void problem2020_5() {
        Scanner scanner = new Scanner(System.in);
        n = scanner.nextInt();
        m = scanner.nextInt();
        k = scanner.nextLong() + 1;
        for (int i = 0; i < dist[0].length; i ++ ) {
            Arrays.fill(dist[i], -1L);
        }
        dfs(0, 0);
    }


    public static void main(String[] args) {
        problem2020_5();
    }
}

dfs,排除等效冗余优化可以ac
发表于 2024-06-14 13:58:47 回复(0)