-1

I am coding in hackerrank and came across this problem: https://www.hackerrank.com/challenges/power-calculation

My code works for small files and big numbers. As for the big files, it times out. Could someone make it more efficient.

My code:

 z = []
def modexp(a, n, m):
    bits = []
    while n:
        bits.append(n%2)
        n /= 2
    solution = 1
    bits.reverse()
    for x in bits:
        solution = (solution*solution)%m
        if x:
            solution = (solution*a)%m
    return solution


for _ in xrange(int(input())): 
    while True: 
            try:
                    x = raw_input()
                    sum =0
                    z = x.split(' ')
                    power = int(z[1])
                    limit = int(z[0])
                    for i in range(0,limit+1): 
                        sum = sum%100 + modexp(i%100,power, pow(10,2))
                    if sum < 10: 
                        print '%02d' % sum 
                    if sum > 10: 
                        print sum%100 
            except: 
                break

Sample data - input:

10
487348 808701
204397 738749
814036 784709
713222 692670
890568 452450
686541 933150
935447 202322
559883 847002
468195 111274
833627 238704

Sample output:

76
13
76
75
24
51
20
54
90
42
qwerty
  • 49
  • 9

1 Answers1

0

One can easily reduce the number of power evaluations by observing that its values mod 100 have a period of 100. Thus decompose K = M*100+L by computing M=K/100; L=K%100;.

Then

  • for k=0 to L the power modexp(k%100,N,100) occurs M+1 times,
  • for k=L+1 to 99 it occurs M times in the sum.

Thus each power sum can be reduced to 99 power computations


One can reduce the effort to compute the powers even more by observing that increasing powers of the same number are periodic in the last two digits. Generally the sequence

1, a % m, a**2 % m, a**3 % m, a**4 % m, ...

becomes periodic after some point that is given by the highest multiplicity of a prime factor. One period length is given by the value of m in Euler's totient function.

The totient value of 100=2²·5² is phi(100)=(2-1)·2·(5-1)·5=40. The offset before the period sets in is at most 2, it follows that for all integers a

a**2 % 100 == a**42 % 100 = a**82 % 100 = ...
a**3 % 100 == a**43 % 100 = a**83 % 100 = ...

and so on.

Which means that for N>41 one can reduce the exponent to N=2+(N-2) % 40. (Indeed one can replace 40 by 20 in that reduction.)


And as a final remark that will not have much impact on running times, only on the complexity of the code:

There is a shorter way to implement modexp, this algorithm is also a standard exercise to identify loop invariants:

def modexp(a, n, m):
    solution = 1
    apower = a
    while n:
        if (n%2): solution = (solution*apower) % m
        n /= 2
        apower = (apower*apower) % m
    return solution
Lutz Lehmann
  • 25,219
  • 2
  • 22
  • 51