Search code examples
pythonpython-3.xmathmodular-arithmetic

Calculating modulus for larger numbers in python


My code works fine with small number but when i do it with large numbers it gives running error

n = int(input().strip())
a=[]
for a_i in range(n): 
  a,n,m = [int(a_temp) for a_temp in input().strip().split(' ')]

  #n = test cases
  #a is a number 
  # n is no of times a will repeat itself (for example a=12 ,n =2 so y=1212.)
  #m is divisor

  y=[a]*n
  #print(y)

  s = map(str, y)   # ['1','2','3']
  s = ''.join(s)          # '123'
  s = int(s)
  #print(s)

  mod=s%m
  print(mod)

INPUT:

2  
12 2 17  
523 3 11

OUTPUT:

5
6

For input like :

2
366 457429086499 164868357
764 438211694736 385254849

It gives error:

Traceback (most recent call last):
  File "C:/Users/LENOVO/AppData/Local/Programs/Python/Python35-32/try123.py", line 11, in <module>
    y=[a]*n
OverflowError: cannot fit 'int' into an index-sized integer

How to fix this?


Solution

  • There is no naïve solution to the problem that works for large numbers. You need to use some clever algebra and/or number theory. 366, 366366, 366366366, ... are partial sums of a geometric series. There is a standard formula for summing them, but unfortunately it involves division which doesn't play nice with modular arithmetic. This answer to the question of how to compute them gives a clever recursive solution which is similar to standard approaches to modular exponentiation. Implementing this in Python and then calling it with the right arguments leads to:

    def geom(a,k,n):
        """calculates (1 + a + a^2 + ... + a^(k-1)) mod n)"""
        if k <= 2:
            return sum(a**i for i in range(k)) % n
        else:
            m = k//2
            b = pow(a,2,n)
            g = ((1+a)*geom(b,m,n))%n
            return g if k%2 == 0 else (g + pow(a,k-1,n))%n
    
    def f(a,m,n):
        """ returns aaaa...a (m times) modulo n"""
        k = len(str(a))
        r = pow(10,k,n)
        return (a*geom(r,m,n))%n
    

    For example,

    >>> f(366, 457429086499,164868357)
    2013258
    

    Which is calculated almost instantaneously.