^ b ^ c的最后一位数字

时间:2015-11-17 19:45:04

标签: math exponentiation

我遇到了这个问题:

  

给出a,b和c三   自然数(例如1 <= a,b,c <= 10 ^ 9),你应该找到数字a ^ b ^ c的最后一位数。“

我首先想到的是用于提高功率n的O(log n)算法。

var xmlPaths = new[]
{
    HttpContext.Current.Server.MapPath("~/bin/Path.To.FirstNamespace.XML"),
    HttpContext.Current.Server.MapPath("~/bin/Path.To.OtherNamespace.XML")
};
var documentationProvider = new XmlDocumentationProvider(xmlPaths);
config.SetDocumentationProvider(documentationProvider);

显然,一些基本的数学可能会有所帮助,比如“最后一位数字”:

   int acc=1; //accumulator
   while(n>0) {
        if(n%2==1)
            acc*=a;
        a=a*a;
        n/=2;
    }

其中n%4是除法的剩余部分n / 4

简而言之,我试图将这些结合起来,但我无法顺利进行。

有些帮助真的会被贬低。

2 个答案:

答案 0 :(得分:6)

问题是b^c可能非常大。因此,您希望在使用标准模幂运算之前减少它。

您可以注意到a^(b^c) MOD 10最多可以包含10个不同的值。

由于鸽笼原则,对于某些p,会有ra^r MOD 10 = a^(p+r) MOD 10 p <= 10 r <= 10

q

这意味着任何a^r MOD 10 = a^r*a^p MOD 10 = (a^r*a^p)*a^p MOD 10 = ... = a^(r+q*p) MOD 10

n = s+r+q*p

对于任何s < pa^n MOD 10 = a^s*a^(r+q*p) MOD 10 = a^s*a^r MOD 10 = a^((n-r) MOD p)*a^r MOD 10 都有:

n= (b^c)

您只需替换上一个等式中的(b^c-r) MOD p即可。

您只需计算p <= 10 a^((b^c-r) MOD p)*a^r MOD 10哪里可以轻松完成,然后计算""

答案 1 :(得分:4)

就像我在评论中提到的那样,这与智能算法没什么关系。使用一些基本数论可以完全减少问题。这将产生O(1)算法。

中国剩余定理说,如果我们知道一些数x模2和模5,我们知道它模10。所以找到一个^ b ^ c模10可以简化为找到一个^ b ^ c模2和a ^ b ^ c modulo 5.费马的小定理说对于任何素数p,如果p不除a,则a ^(p-1)= 1(mod p),所以a ^ n = a ^ (n mod(p-1))(mod p)。如果p确实除了a,则显然对于任何n> 1,^ n = 0(mod p)。注意,对于任何n> 0,x ^ n = x(mod 2),所以a ^ b ^ c = a(mod 2)。

剩下的就是找到一个^ b ^ c mod 5,它减少到找到b ^ c mod 4.不幸的是,我们既不能使用中文余数定理,也不能使用Fermat的小定理。但是,mod 4只有4种可能性,所以我们可以单独检查它们。如果我们从b = 0(mod 4)或b = 1(mod 4)开始,那么当然b ^ c = b(mod 4)。如果我们有b = 2(mod 4)那么很容易看出如果c = 1则b ^ c = 2(mod 4),并且如果c> 1,则b ^ c = 0(mod 4)。 1.如果b = 3(mod 4),那么如果c是偶数则b ^ c = 3,如果c是奇数则b ^ c = 1。这给了我们任何b和c的b ^ c(mod 4),然后给我们一个^ b ^ c(mod 5),所有这些都是在恒定的时间内。

最后用^ b ^ c = a(mod 2)我们可以使用中国余数定理来找到^ b ^ c(mod 10)。这需要(x(mod 2),y(mod 5))和z(mod 10)之间的映射。中国剩余定理只告诉我们这种映射是双射的,它并没有告诉我们如何找到它。但是,只有10个选项,因此可以在一张纸上或使用一个小程序轻松完成。一旦我们找到这个映射,我们只需将它存储在一个数组中,我们就可以在O(1)中完成整个计算。

顺便说一下,这将是我在python中实现的算法:

# this table only  needs to be calculated once
# can also be hard-coded
mod2mod5_to_mod10 = [[0 for i in range(5)] for j in range(2)]
for i in range(10):
    mod2mod5_to_mod10[i % 2][i % 5] = i

[a,b,c] = [int(input()) for i in range(3)]

if a % 5 == 0:
    abcmod5 = 0
else:
    bmod4 = b % 4
    if bmod4  == 0 or bmod4 == 1:
        bcmod4 = bmod4 
    elif bmod4 == 2:
        if c == 1:
            bcmod4 = 2
        else:
            bcmod4 = 0
    else:
        if c % 2 == 0:
            bcmod4 = 1
        else:
            bcmod4 = 3

    abcmod5 = ((a % 5)**bcmod4) % 5

abcmod2 = a % 2

abcmod10 = mod2mod5_to_mod10[abcmod2][abcmod5]

print(abcmod10)