問題
現在有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:
1
8 1 100
輸出例子1:
63
思路及解答
# Case 通過率 0%
# 把 [l, r] 區間內的數進行進制轉換,之後計數,輸出次數最多的那個數。
q = int(input())
nums, k, l, r = [], [], [], []
for i in range(q):
times = 0
nums = list(map(int, input().split()))
k = nums[0]
l = nums[1]
r = nums[2]
result = l
for j in range(l, r+1):
item = j
tmp = [j%k]
j = j // k
while (j):
tmp.append(j%k)
j = j // k
tmp = tmp[::-1]
# times = tmp.count(k-1) > times ? tmp.count(k-1) : times # 這是 C 語言中的三目運算符
result = item if tmp.count(k-1) > times else result # 這是 Python 中的三目運算符
times = tmp.count(k-1) # 問題出在這裏,如果本次次數不大於上次次數,那麼次數是不更新的,所以這條語句應該放在 if 語句裏面。
print(result)
# 超時。Case 通過率 20%
q = int(input())
nums, k, l, r = [], [], [], []
for i in range(q):
times = 0
nums = list(map(int, input().split()))
k = nums[0]
l = nums[1]
r = nums[2]
result = l
for j in range(l, r+1):
item = j
tmp = [j%k]
j = j // k
while (j):
tmp.append(j%k)
j = j // k
tmp = tmp[::-1]
# times = tmp.count(k-1) > times ? tmp.count(k-1) : times
# result, times = item, tmp.count(k-1) if tmp.count(k-1) > times # 這個寫法不對,我也不清楚爲何。
if tmp.count(k-1) > times:
result = item
times = tmp.count(k-1)
print(result)
# 不需要數 k-1 的個數,因爲輸出的是滿足條件的最小數,只需要從最低位開始變成 k-1,如果位數超出 lleft,那麼在前面補 k-1
# 這是思路,我還沒有改對,因爲最開始進制轉換 d2k 這個函數也是用數值計算的,而不是列表,最後造成超過十的進制全部出錯,因爲假如一個十六進制的數 12,會被拆成 1,2 兩個數,所以進制轉換時最好避免使用數學計算和字符串!
# 我還沒改對,目前我不想在改了。。。。
q = int(input())
def k2d(num, k): # k 進制轉化爲十進制,輸出爲 int
res = 0
numstr = list(str(num))
l = len(numstr)
for i in range(l):
res += int(numstr[i]) * k**(l-i-1)
return res
def d2k(num, k): # 十進制轉換爲 k 進制,輸出爲 list
res = []
while not num:
res.append(num%k)
num = num // k
return res
def getnum(length, k): # 獲得 length 長度的全部爲 k-1 元素的數,輸出爲 list
res = []
for i in range(length):
res.append((k-1))
return res
def replacenum(List, n, k): # 將 List 最後 n 項變爲 k-1,輸出爲 str
l = len(List)
res = List[: l-n]
for i in range(l-n, l):
res += str(k-1)
return res
def str2int(ListString): # 把字符串列表轉換爲對應的整數
res = 0
l = len(ListString)
for i in range(l):
res += int(ListString[i]) * 10**(l-i-1)
return res
def addnum(Str, n, k): # 在 Str 前補 n 個 k-1
res = str(k-1) * n + Str
return res
for i in range(q):
nums = list(map(int, input().split()))
k = nums[0]
l = nums[1]
r = nums[2]
l, r = d2k(l, k), d2k(r, k)
lleft, lright = len(list(str(l))), len(list(str(r)))
lstr, rstr = list(str(l)), list(str(r))
m = 1
while (m <= lleft):
tmp0 = str2int(replacenum(lstr, m, k))
if l <= str2int(replacenum(lstr, m, k)) <= r:
m += 1
else:
print(k2d(str2int(replacenum(lstr, m-1, k)), k))
break
m = lleft + 1
if tmp0 <= r:
n = 1
tmp1 = str2int(addnum(str(tmp0), n, k))
while(str2int(addnum(str(tmp0), n, k)) <= r):
n += 1
tmp2 = k2d(str2int(addnum(str(tmp0), n-1, k)), k)
print(k2d(str2int(addnum(str(tmp0), n-1, k)), k))
# 低位變 k-1 時,巧妙做法:假如百位數是5(八進制),那麼變成七(八進制數百位)要加 2,對應十進制數要加 2*(8^2)
import java.util.ArrayList;
import java.util.Scanner;
public class Main {
public static long minNum(int k, long start, long end) {
ArrayList<Integer> list = new ArrayList<Integer>();
long tmp = start;
while (tmp != 0) {
long rest = tmp % k;
list.add((int) rest);
tmp = tmp / k;
}
long sum = 1;
for (int i = 0; i < list.size(); i++) {
long num = list.get(i);
num = k - 1 - num;
long size = (long) (num * sum);
if (start + size <= end) {
start = start + size;
} else {
return start;
}
sum = sum * k;
}
while (start < end) {
long size = (long) ((k - 1) * sum);
if (start + size <= end) {
start = start + size;
} else {
return start;
}
sum = sum * k;
}
return start;
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (in.hasNextInt()) { //while循環沒用 沒有就可以
int time = in.nextInt();
for (int i = 0; i < time; i++) {
int k = in.nextInt();
long start = in.nextLong();
long end = in.nextLong();
System.out.println(minNum(k, start, end)); //這個真的值得學習 在每一次小循環中就輸出一次答案 所以一定要編寫函數
}
}
}
}
知識點
1. .count(item) 可以用於字符串,也可以用於列表,用來記字符串中或列表中 item 出現的次數。
即:string.count() 和 list.count()。
(參考:Python中的三目運算符(三元表達式))
2. 列表去重
nums = list(set(numsList))
3. 進制轉換(儘量避免使用數學計算、字符串)
(1) 十進制轉 k 進制
def d2k(num, k): # 十進制轉換爲 k 進制,輸出爲 list
res = []
while num:
res.append(num%k)
num = num // k
return res[::-1] # 倒序輸出
(2) k進制轉十進制
def k2d(num, k): # k 進制轉化爲十進制,輸出爲 int
res = 0
numstr = list(str(num))
l = len(numstr)
for i in range(l):
res += int(numstr[i]) * k**(l-i-1)
return res
4. 函數模塊的合理使用!!!