python 最低基数系统,其数字中全部为1

thtygnil  于 2022-12-17  发布在  Python
关注(0)|答案(2)|浏览(92)

我需要确定一个最小的数制,在这个数制中,输入n(以10为基数)的数字都是1。
例:以2为底的7等于111 - fits!答案是2

21 in base 2 is 10101 - contains 0, does not fit
21 in base 3 is 210 - contains 0 and 2, does not fit
21 in base 4 is 111 - contains only 1 it fits! answer is 4

n is always less than Number.MAX_SAFE_INTEGER or equivalent.

我有下面的代码,它可以很好地处理一定范围内的数字,但对于巨大的数字,算法仍然很耗时:

def check_digits(number, base):
    res = 1
    while res == 1 and number:
        res *= number % base
        number //= base
    return res

def get_min_base(number):
    for i in range(2, int(number ** 0.5) + 2):
        if check_digits(number, i) == 1:
            return i
    return number - 1

如何优化当前代码以使其运行得更快?

6rqinv9w

6rqinv9w1#

b为底的x 1字符串表示的数字是b^(x-1) + b^(x-2) + ... + b^2 + b + 1
请注意,对于x >= 3,此数字大于b^(x-1)(一般)且小于(b+1)^(x-1)(应用二项式定理)。因此,如果一个数nx 1 s表示,以b为底,我们有b^(x-1) < n < (b+1)^(x-1)。应用x-1次根,我们有b < n^(1/(x-1)) < b+1。因此,要使b存在,b必须是floor(n^(1/(x-1))
到目前为止,我一直使用^表示法而不是Python风格的**语法,因为这些等式和不等式只适用于精确的真实的运算,而不适用于浮点运算。如果您尝试使用浮点运算来计算b,舍入误差可能会打乱您的计算。特别是对于ULP大于1的超大输入。(我 * 认为 * 浮点适合您使用的输入范围,但我不确定。)
尽管如此,不管浮点数是否足够好,或者您是否需要更花哨的东西,算法的思想都在那里:可以通过直接计算对应的b必须是什么,并检查基b中的x1是否真正表示n,来直接检查x的值是否可行。

6yt4nkrj

6yt4nkrj2#

只是一些小的转折,稍微快一点,但没有提高时间复杂度。

def check_digits2(number, base):
    while number % base == 1:
        if number == 1:
            return True
        number //= base
    return False

def get_min_base2(number):
    for i in range(2, int(number**0.5) + 2):
        if check_digits2(number, i):
            return i
    return number - 1

def test():
    number = 100000010000001

    start = time.time()
    print(get_min_base(number))             # 10000000
    print(f"{time.time() - start:.3f}s\n")  # 3.292s

    start = time.time()
    print(get_min_base2(number))            # 10000000
    print(f"{time.time() - start:.3f}s\n")  # 1.731s

也尝试一些数学技巧的方法,但我实际上使它更糟,哈哈

def calculate_n(number, base):
    return math.log(number * (base - 1) + 1, base).is_integer()

def get_min_base3(number):
    for i in range(2, int(number**0.5) + 2):
        if calculate_n(number, i):
            return i
    return number - 1

def test():
    number = 100000010000001

    start = time.time()
    print(get_min_base3(number))            # 10000000
    print(f"{time.time() - start:.3f}s\n")  # 4.597s

相关问题