【20190812】【校招筆試題】Bittttttts_360(待續)

問題

現在有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. 函數模塊的合理使用!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章