Kaosar and GCD#12273

Kaosar and GCD (Editorial)

Problem Author:

AlKaosar Hussain

Prepared by:

Hasan Saleh (MathModel)

Edited by:

Hasan Saleh (MathModel)

Solution We are taking the numbers

\binom{n}{1}, \binom{n}{2}, \dots, \binom{n}{m}

and we want

\gcd\bigl(\binom{n}{1},\binom{n}{2},\dots,\binom{n}{m}\bigr).

The clean way to do this is to look at it prime by prime. Let

n = \prod_{p} p^{e_p}

be the prime factorization of . The gcd of the binomials will also be a divisor of , so it will have the form

\prod_{p \mid n} p^{f_p}

for some f_p \le e_p. Our job is to find, for every prime that divides , what is the smallest power of that appears in all of

\binom{n}{1}, \binom{n}{2}, \dots, \binom{n}{m}.

That "smallest power" is exactly

f_p = e_p - \bigl\lfloor \log_p m \bigr\rfloor,

but never negative (if it becomes negative, we just put ).

Why is that true? Fix a prime and suppose has -adic valuation , i.e. n = p^e \cdot r with \gcd(r,p)=1. Now look at the binomial with k = p^t where

t = \bigl\lfloor \log_p m \bigr\rfloor \quad\text{so}\quad p^t \le m < p^{t+1}.

This is inside our range 1 \le k \le m. For this special one can check (this is a standard fact and can be proved with carries in base or by looking at factorials) that

v_p\bigl(\binom{n}{p^t}\bigr) = e - t.

So for this particular the power of inside \binom{n}{k} is exactly p^{e-t}. This already shows that the gcd cannot have more than p^{e-t}.

The second part is that for any k \le m you cannot get a smaller -power than e - t. Intuitively: to "kill" more powers of in the binomial, would have to contain more factors of in , but up to you can only gain at most \lfloor \log_p m \rfloor factors from the denominator, so the exponent in the binomial stays \ge e - \lfloor \log_p m \rfloor. Therefore the minimum over all k \in [1,m] is exactly

\min_{1 \le k \le m} v_p\bigl(\binom{n}{k}\bigr) = e - \bigl\lfloor \log_p m \bigr\rfloor \quad (\text{but not below }0).

Putting this together over all primes dividing , we get

\gcd_{1 \le k \le m} \binom{n}{k} = \prod_{p^e \parallel n} p^{\max\{0,\, e - \lfloor \log_p m \rfloor\}}.

The code does exactly that:

  • factor into primes with exponents ;

  • for each compute \texttt{flog}(m,p) which is literally

    \texttt{flog}(m,p) = \left\lfloor \log_p m \right\rfloor

    by repeatedly dividing by ;

  • if e > \texttt{flog}(m,p) we multiply the answer by p^{e-\texttt{flog}(m,p)}.

Complexity is \mathcal{O}(\sqrt{n}).

def flog(m,p):
    t=0
    while m>=p:
        m//=p
        t+=1
    return t

def g(n,m):
    ans=1;x=n;i=2
    while i*i<=x:
        e=0
        while x%i==0:
            x//=i
            e+=1
        if e:
            t=flog(m,i)
            if e>t: ans*=i**(e-t)
        i+=1
    if x>1:
        t=flog(m,x)
        if 1>t: ans*=x**(1-t)
    return ans

for _ in range(int(input())):
    n,m=map(int,input().split())
    print(g(n,m))