计算 x1 ^ (x2 ^ (x3 ^ (... ^ xn))) 的最后一个(十进制)数字

Posted

技术标签:

【中文标题】计算 x1 ^ (x2 ^ (x3 ^ (... ^ xn))) 的最后一个(十进制)数字【英文标题】:Compute the last (decimal) digit of x1 ^ (x2 ^ (x3 ^ (... ^ xn))) [duplicate] 【发布时间】:2018-12-28 15:18:32 【问题描述】:

我需要从作为列表传递给函数的整数中找到x1 ^ (x2 ^ (x3 ^ (... ^ xn))) 的个位。 例如,输入 [3, 4, 2] 将返回 1,因为 3 ^ (4 ^ 2) = 3 ^ 16 = 43046721 的最后一位是 1。 该函数需要尽可能高效,因为显然尝试计算767456 ^ 981242 不是很快。

我尝试了一些方法,但我认为解决这个问题的最佳方法是使用序列。例如,任何以1 结尾的数字,当提升到幂时,总是以1 结尾。对于2,生成的数字将以2, 4, 6 or 8 结尾。 如果一个数字是幂次方,则结果数字的最后一位数字将遵循基于指数最后一位数字的模式:

1:序列为 1

2:序列为 2、4、8、6

3:序列为 3、9、7、1

4:序列为 4、6

5:序列为 5

6:序列为 6

7:序列为 7、9、3、1

8:序列为 8、4、2、6

9:序列为 9, 1

0:序列为0

我认为计算整个最后一位数字的最简单方法是通过列表向后工作,并一次计算每个计算的最后一位数字,直到我回到开始,但我不知道该怎么做? 如果有人可以帮助或建议另一种与此相同或更有效的方法,将不胜感激。

到目前为止我有这段代码,但它不适用于非常大的数字

def last_digit(lst):
    if lst == []:
        return 1

    total = lst[len(lst)-2] ** lst[len(lst)-1]
    for n in reversed(range(len(lst)-2)):
        total = pow(lst[n], total)

    return total%10

编辑:0 ^ 0 应假定为 1

【问题讨论】:

@MattTimmermans 那是 javascript。我不知道如何在 python 中复制它 您已经很好地列出了这些序列。您为什么不尝试充实您的解决方案以实际利用它们呢?在你用尽所有想法后寻找替代或最佳解决方案,序列是一个好的开始。问问自己,如何才能以某种方式在逻辑中使用它们。 @ParitoshSingh 并不意味着粗鲁或任何东西,但我复制的代码是一个更早的尝试,正如我在我的问题中所说,我不知道如何使用这些序列来保持循环找到正确答案 别担心,你们都很好。我想在这种情况下,我可以给出的一个提示是:给定起始数字,比如 8,给定 5 的幂,你会得到什么结果? 9点呢?说13?你看到模式了吗? 什么都没有,如果你正在解决这个问题来娱乐,你可能想看看projecteuler.net这是一个包含数百个主要需要编程来解决的娱乐性数学问题的网站。 【参考方案1】:

x^n = x^(n%4) 因为最后一位数字的句号总是 4。

x  ^2  ^3  ^4  ^5

1   1   1   1   1
2   4   8   6   2
3   9   7   1   3
4   6   4   6   4
5   5   5   5   5
6   6   6   6   6
7   9   3   1   7
8   4   2   6   8
9   1   9   1   9

如您所见,所有 9 位数字的句点均为 4,因此我们可以使用 %4 来简化计算。

如果我们这样做,还有一个模式 %4。

x  ^0  ^1  ^2  ^3  ^4  ^5  ^6  ^7  ^8  ^9
1   1   1   1   1   1   1   1   1   1   1
2   1   2   0   0   0   0   0   0   0   0
3   1   3   1   3   1   3   1   3   1   3
4   1   0   0   0   0   0   0   0   0   0
5   1   1   1   1   1   1   1   1   1   1    (all %4)
6   1   2   0   0   0   0   0   0   0   0
7   1   3   1   3   1   3   1   3   1   3
8   1   0   0   0   0   0   0   0   0   0
9   1   1   1   1   1   1   1   1   1   1

如图所示,当 n>1 时,每个 x 都有一个模式。因此,当 n>1 时,您可以看到 (x^n)%4 = (x^(n+4k))%4。然后,我们可以通过将 4 添加到 n 来防止由 n=0 和 n=1 引起的问题。这是因为,如果 (x^n)%4 = (x^(n+4k))%4,那么 (x^n)%4 = (x^(n%4+4))%4 也是如此。

powers = [3, 9, 7, 1]

lastDigit = 1

for i in range(len(powers) - 1, -1, -1):
    if lastDigit == 0:
        lastDigit = 1
    elif lastDigit == 1:
        lastDigit = powers[i]
    else:
        lastDigit = powers[i]**(lastDigit%4+4)

print(lastDigit%10)

【讨论】:

[7, 6, 21] 对我不起作用。我得到了49,而不是1 @HarryDay 你确定它是要返回 1 吗?我已经计算出返回 9(现在可以了。) 我很确定 @HarryDay 啊,是的,你是对的。现在应该可以解决了。 你的分析有缺陷;虽然a^b^c^d^...z % 10 = a^(b^c^d^...z % 4) % 10 是真的,但这并不意味着b^c^d^...z % 4 = b^(c^d^...z % 4) % 4。无论如何,您的代码都可以正常工作,因为 % 4 的句点几乎与 % 10 的句点兼容,并且不兼容性由您的临时特殊情况处理,但您的分析不足以表明它工作。【参考方案2】:

这更像是数学而不是编程。请注意,您列出的所有序列的长度都是 1、2 或 4。更准确地说,x^4 总是以 0, 1, 5, 6 结尾,x^(4k) 也是如此。所以如果你知道x^(m mod 4) mod 10,你就知道x^m mod 10

现在,计算x2^(x3^(...^xn)) mod 4。故事非常相似,x^2 mod 4 是以太 0 如果x=2k1 如果x=2k+1 (为什么?)。所以

    如果 x2 == 0 则为 0 如果 x2 > 0 且 x3 == 0 则为 1

    如果x2 是偶数,那么它要么是2,要么是0,而2 仅在x2 mod 4 == 2 and (x3==1 or (any x4,...xn == 0) ) 时出现。

    如果x2 是奇数,那么x2^2 mod 4 == 1,所以如果x3 是偶数,我们得到1,否则x2 mod 4

足够的数学,让我们谈谈编码。可能有一些我没有涵盖的极端情况,但它应该适用于大多数情况。

def last_digit(lst):
    if len(lst) == 0:
        return 1

    x = lst[0] % 10
    if len(lst) == 1:
        return x

    # these number never change
    if x in [0,1,5,6]:
        return x

    # now we care for x[1] ^ 4:
    x1 = x[1] % 4

    # only x[0] and x[1]
    if len(lst) == 2 or x1==0:
        return x[0] ** x1 % 10

    # now that x[2] comes to the picture
    if x1 % 2: # == 1
        x1_pow_x2 = x1 if (x[2]%2) else 1
    else: 
        x1_pow_x2 = 2 if (x1==2 and x[2]%2 == 1) else 0

    # we almost done:
    ret = x ** x1_pow_x2 % 10

    # now, there's a catch here, if x[1]^(x[2]^...^x[n-1]) >= 4, 
    # we need to multiply ret with the last digit of x ** 4
    if x[1] >=4 or (x[1] > 1 and x[2] > 1):
        ret = (ret * x**4) % 10

    return ret

【讨论】:

由于我不明白,能否请您再解释一下? @HarryDay 查看已编辑了解更多详情 那么我怎样才能使用它来创建一个给我正确结果的函数呢? 我想这是由于 en.wikipedia.org/wiki/Euler%27s_theorem ,由于一些运气,这里适用。请注意phi(10)=4phi(4)=2 序列可以是任意长度。【参考方案3】:

根据您的序列想法并充实它,您会想要创建一个可以映射所有相关序列的字典。

mapping = 
for i in range(1, 10):
    mapping[i] = [i]
    last_digit = i
    while True:
        last_digit *= i
        last_digit = last_digit%10
        if last_digit in mapping[i]:
            break
        else:
            mapping[i].append(last_digit)

print(mapping)

这会产生输出:映射

1: [1],
 2: [2, 4, 8, 6],
 3: [3, 9, 7, 1],
 4: [4, 6],
 5: [5],
 6: [6],
 7: [7, 9, 3, 1],
 8: [8, 4, 2, 6],
 9: [9, 1]

现在可以开始真正的逻辑了,关键是在序列完成后模式会自我重复。因此,如果您只是使用模数并找出它应该占据序列的哪个位置,那么功率有多大并不重要。

def last_digit_func(lst, mapping):
    if lst == []: #taken from OP
        return 1
    last_digit = lst[0] % 10
    if 0 in lst[1:]: #edge case 0 as a power
        return 1
    if last_digit == 0: #edge case 0 at start
        return last_digit

    for current_power in lst[1:]:
        if len(mapping[last_digit]) == 1:
            return last_digit
        ind = current_power % len(mapping[last_digit])
        ind -= 1 #zero indexing, but powers start from 1. 
        last_digit = mapping[last_digit][ind]
    return last_digit

test1 = [3, 4, 2]
print(last_digit_func(test1, mapping)) #prints 1 

我通过计算 python 中的幂验证了这一点。

test2 = [767456 , 981242]
print(last_digit_func(test2, mapping)) #prints 6

我试图通过在 python 中运行它来验证这一点......我现在后悔了,我的程序仍在尝试解决它。哦,好吧:)

【讨论】:

这几乎可以工作,但是在某些情况下它对我不起作用。我忘了在原帖中说,但0 ^ 0 应该被假定为1 @HarryDay 现在怎么样,我没有意识到 0 会被允许 @HarryDay Python 自动计算 0^0 为 1,所以这应该不会有太大的不同。 这很重要,因为我从未在实际解决方案中实际计算过单个功率。 你的行 if 0 in lst[1:] 并没有解决 0 的问题。取 lst = [2, 2, 0, 2]。根据这一行,它将返回一个,但它应该返回 2^(2^(0^2)) = 2^(2^0) = 2^1 = 2

以上是关于计算 x1 ^ (x2 ^ (x3 ^ (... ^ xn))) 的最后一个(十进制)数字的主要内容,如果未能解决你的问题,请参考以下文章

*1034计算三角形面积

方程x1+x2+x3+x4=5的非负整数解的个数怎么求?

求X1+X2+X3+X4=10的自然数解有多少

利用MATLAB求方程y1=3x1+x2+x3,y2=3x1-x2-x3在x1=-2,x2=3,x3=1时的值

matlab中solve函数的用法。悬赏20分

规范化例题