Bittttttts

题目

题目连接:Bittttttts

现在有 q 个询问,每次询问想问你在 [l, r] 区间内,k 进制表示中,k - 1 的数量最多的数是哪个数。

比如当 k = 2 时,9 的二进制就是 1001,那么他就有 2 个 1。

输入描述

第一行一个 q,表示有 q 组询问。
接下来 q 行,每行三个整数 k,l,r,分别表示进制数,查询的数字,以及查询的范围。
满足 1 <= q <= 100000,2 <= k <= 16,1 <= l <= r <= 10^16

输出描述

对于每组询问,输出答案。如果有多个答案,请输出最小的。

样例输入

1
8 1 100

样例输出

63

代码

import java.util.ArrayList;
import java.util.Scanner;

/**
 * 思路:
 *      先将 l 转换为 k 进制,然后从低位到高位依次将每一位变成 k - 1
 *      在变换之前,先看能不能变,能则变,不能则表示当前数值已经超过了 r,直接跳出
 *
 * 这样写会超时,在牛客上只能过86%,但没关系,思路很重要!!!
 */
public class Main {

    private static long getNum(int k, long l, long r) {
        ArrayList<Integer> list = new ArrayList<>();
        long tem = l;
        // 先将 l 转换为 k 进制,放入 list 中
        while (tem != 0) {
            long mod = tem % k;
            list.add((int) mod);
            tem /= k;
        }

        long curFactor = 1;
        for (int i = 0; i < list.size(); i++) {
            int diff = k - 1 - list.get(i);
            long add = diff * curFactor;
            if (l + add <= r)
                l += add;
            else
                return l;
            curFactor *= k;
        }
        while (l + curFactor * (k - 1) <= r) {
            l += curFactor * (k - 1);
            curFactor *= k;
        }
        return l;
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int q = scanner.nextInt();
        int k;
        long l, r;
        while (q-- > 0) {
            k = scanner.nextInt();
            l = scanner.nextLong();
            r = scanner.nextLong();
            System.out.println(getNum(k, l, r));
        }
    }
}
原文地址:https://www.cnblogs.com/debugxw/p/11410955.html