题目
现在有 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));
}
}
}