【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. 函数模块的合理使用!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Satisfying

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值