Sort by

recency

|

6 Discussions

|

  • + 0 comments

    Looking at the leaderboard (language=Python3) I find that nearly everyone submits the same solution (the one that TChalla copied below).
    Could anyone help me understand, why?
    (what sense does this make, what is the personal advantage?)

  • + 1 comment

    Python3 solution

    # Enter your code here. Read input from STDIN. Print output to STDOUT
    def euclid(a, b):
        if b == 0:
            return (a, 1, 0)
        q = a // b
        g, u, v = euclid(b, a - q * b)
        return (g, v, u - q * v)
    
    def modInverse(a, m):
        (g, u, v) = euclid(a, m)
        assert(g == 1)
        return u % m
    
    def dpow(x, p, one, mul):
        ret = one
        while p > 0:
            if p % 2 == 1:
                ret = mul(ret, x)
            p //= 2
            x = mul(x, x)
        return ret
    
    # find min t <=limit: x^t==y
    def dLog(x, y, one, mul, inv, limit):
        step = 1
        while step * step < limit:
            step += 1
        d = dict()
        invx = inv(x)
        cur = mul(invx, y)
        for i in range(1, step + 1):
            if cur not in d:
                d[cur] = i
            cur = mul(cur, invx)
        ret = limit + 1
        cur = one
        xstep = dpow(x, step, one, mul)
        for i in range(step):
            if cur in d:
                ret = min(ret, step * i + d[cur])
            cur = mul(cur, xstep)
        return -1 if ret == limit + 1 else ret
    
    def mul(p1, p2):
            a1, b1 = p1
            a2, b2 = p2
            return ((a1 * a2 + b1 * b2 * 5) % m, (a1 * b2 + a2 * b1) % m)
    
    def norm(p):
        a, b = p
        return (a * a - b * b * 5) % m
    
    def inv(p):
        assert(norm(p) == 1)
        a, b = p
        return (a, -b)
        
    tests = int(input())
    for test in range(tests):
        a, b, m = map(int, input().split())
        x = (a, b)
        xlen = norm(x)
        if euclid(xlen, m)[0] != 1:
            print(-1)
            continue
        plen = dLog(xlen, 1, 1, lambda a, b: (a * b) % m, lambda a: modInverse(a, m), m)
        x = dpow(x, plen, (1, 0), mul)
        pdir = dLog(x, (1, 0), (1, 0), mul, inv, 10 * m)
        assert(plen != -1)
        print(plen * pdir)
    
  • + 0 comments

    The editorial seems to be assuming that m is a prime number. (Although I experimentally solved for non-prime cases)

  • + 0 comments

    For people who already solved it, the idea used here is useful for finding period in many other similar recurrent sequences, such as Fibonacci numbers. Notice that, for any such sequence modulo p, the order is at most p^2. So first you need to find M such that the sequence surely repeats after a[M]. And if it is periodic, then you will also see that the order is a divisor of this M

  • + 1 comment

    Hi, I had a python solution to the problem based on baby-step giant-step algorithm to find discrete log but I got TLE, if someone can help me to optimize the solution, thanks in advance.

    """ Here I show how to find a discrete log using baby step big step algorithms, Code """

    def gcd(a,b): if a%b==0:return b,0,1 r,x,y=gcd(b,a%b) return r,y,x-(a/b)*y

    def inv(a,b,m): k=(a**2-5*b**2)%m g,k,_=gcd(k,m) k%=m if g!=1:return None return ((a*k)%m,(-b*k)%m)

    def pow(x,n,one,mul):

    r=one
    while n:
        if n%2:r=mul(r,x)
        n/=2
        x=mul(x,x)
    return r
    

    import math

    def dLog(x,y,one,mul,inv,group_size): step=int(math.sqrt(group_size))+1

    xinv=inv(x)
    if not xinv:return -1
    r=y
    d={}
    for i in range(1,step+1):
        r=mul(r,xinv)
        if r not in d:d[r]=i
    
    current=one
    ret=step**2+1
    
    r=pow(x,step,one,mul)
    
    for i in range(0,step+1):       
        if current in d:            
            ret=min(i*step+d[current],ret)
        current=mul(current,r)
    return -1 if ret==step+1 else ret
    

    def solve(a,b,m):

    def mul(v1,v2):
        a1,b1=v1
        a2,b2=v2
        return ((a1*a2+5*b1*b2)%m,(a1*b2+b1*a2)%m)
    
    
    return dLog((a,b),(1,0),(1,0),mul,lambda v:inv(v[0],v[1],m),m*m)
    

    T=input()

    for i in range(T): a,b,m=map(int,raw_input().strip().split()) print solve(a,b,m)