Vika and Stone Skipping (Codeforces 1848E)
Tags: Math, number theory

In Vika's hometown, Vladivostok, there is a beautiful sea.Often you can see kids skimming stones. This is the process of throwing a stone into the sea at a small angle, causing it to fly far and bounce several times off the water surface.Vika has skimmed stones many times and knows that if you throw a stone from the shore perpendicular to the coastline with a force of $$$f$$$, it will first touch the water at a distance of $$$f$$$ from the shore, then bounce off and touch the water again at a distance of $$$f - 1$$$ from the previous point of contact. The stone will continue to fly in a straight line, reducing the distances between the points where it touches the water, until it falls into the sea.Formally, the points at which the stone touches the water surface will have the following coordinates: $$$f$$$, $$$f + (f - 1)$$$, $$$f + (f - 1) + (f - 2)$$$, ... , $$$f + (f - 1) + (f - 2) + \ldots + 1$$$ (assuming that $$$0$$$ is the coordinate of the shoreline).Once, while walking along the embankment of Vladivostok in the evening, Vika saw a group of guys skipping stones across the sea, launching them from the same point with different forces.She became interested in what is the maximum number of guys who can launch a stone with their force $$$f_i$$$, so that all $$$f_i$$$ are different positive integers, and all $$$n$$$ stones touched the water at the point with the coordinate $$$x$$$ (assuming that $$$0$$$ is the coordinate of the shoreline).After thinking a little, Vika answered her question. After that, she began to analyze how the answer to her question would change if she multiplied the coordinate $$$x$$$ by some positive integers $$$x_1$$$, $$$x_2$$$, ... , $$$x_q$$$, which she picked for analysis.Vika finds it difficult to cope with such analysis on her own, so she turned to you for help.Formally, Vika is interested in the answer to her question for the coordinates $$$X_1 = x \cdot x_1$$$, $$$X_2 = X_1 \cdot x_2$$$, ... , $$$X_q = X_{q-1} \cdot x_q$$$. Since the answer for such coordinates can be quite large, find it modulo $$$M$$$. It is guaranteed that $$$M$$$ is prime.

Input: The first line of the input contains three integers $$$x$$$ ($$$1 \le x \le 10^9$$$), $$$q$$$ ($$$1 \le q \le 10^5$$$) and $$$M$$$ ($$$100 \le M \le 2 \cdot 10^9$$$) — the initial coordinate for which Vika answered the question on her own, the number of integers $$$x_i$$$ by which Vika will multiply the initial coordinate and prime module $$$M$$$.The second line of the input contains $$$q$$$ integers $$$x_1, x_2, x_3, \ldots, x_q$$$ ($$$1 \le x_i \le 10^6$$$) — the integers described in the statement.

Output: Output $$$q$$$ integers, where the $$$i$$$-th number corresponds to the answer to Vika's question for the coordinate $$$X_i$$$. Output all the answers modulo $$$M$$$.

Note: In the first sample, to make the stone touch the water at a point with coordinate $$$2$$$, it needs to be thrown with a force of $$$2$$$. To make the stone touch the water at a point with coordinate $$$2 \cdot 3 = 6$$$, it needs to be thrown with a force of $$$3$$$ or $$$6$$$.In the second sample, you can skim a stone with a force of $$$5$$$ or $$$14$$$ to make it touch the water at a point with coordinate $$$7 \cdot 2 = 14$$$. For the coordinate $$$14 \cdot 13 = 182$$$, there are $$$4$$$ possible forces: $$$20$$$, $$$29$$$, $$$47$$$, $$$182$$$.

Sample Inputs:
1 2 179
2 3

7 5 998244353
2 13 1 44 179

1000000000 10 179
58989 49494 8799 9794 97414 141241 552545 145555 548959 774175

Sample Outputs:
1
2

2
4
4
8
16

120
4
16
64
111
43
150
85
161
95

Solution (Python):
def II():
    return int(input())

def LMI():
    return list(map(int, input().split()))

def I():
    return input()

def MII():
    return map(int, input().split())
import sys
input = sys.stdin.readline
import math
prime = [0, 0] + [-1] * (10 ** 6 - 1)
for i in range(2, 10 ** 6 + 1):
    if prime[i] == -1:
        for j in range(i, 10 ** 6 + 1, i):
            prime[j] = i
for l in range(1):
    (x, q, M) = MII()
    Q = LMI()
    cnt = [0] * (10 ** 6 + 1)
    ans = 1
    while x % 2 == 0:
        x //= 2
    p = x
    cc = 0
    for i in range(3, 10 ** 6 + 1):
        while x % i == 0:
            x //= i
            cnt[i] += 1
        aa = cnt[i] + 1
        while aa % M == 0:
            cc += 1
            aa //= M
        ans = ans % M * (aa % M) % M
    if x > 1:
        ans *= 2
        ans %= M
    for i in range(q):
        x = Q[i]
        while x % 2 == 0:
            x //= 2
        while prime[x]:
            aa = cnt[prime[x]] + 1
            while aa % M == 0:
                aa //= M
                cc -= 1
            ans *= pow(aa % M, M - 2, M)
            ans %= M
            cnt[prime[x]] += 1
            aa = cnt[prime[x]] + 1
            while aa % M == 0:
                aa //= M
                cc += 1
            ans *= aa % M
            ans %= M
            x //= prime[x]
        if cc:
            print(0)
        else:
            print(ans)

Solution (Python):
def f(n):
    while n % 2 == 0:
        n //= 2
    return n
sieve = [0] * (10 ** 6 + 1)
for i in range(2, 10 ** 6 + 1):
    if sieve[i] == 0:
        for j in range(i, 10 ** 6 + 1, i):
            if sieve[j] == 0:
                sieve[j] = i
from collections import defaultdict
(x, q, M) = map(int, input().split())
query = list(map(int, input().split()))
d = defaultdict(int)
res = 1
x = f(x)
y = set()
cnt = 0
while x > 1:
    for i in range(2, int(x ** (1 / 2)) + 1):
        if x % i == 0:
            while x % i == 0:
                d[i] += 1
                x //= i
            if (d[i] + 1) % M == 0:
                cnt += 1
                y.add(i)
            else:
                res *= d[i] + 1
                res %= M
            break
    else:
        d[x] += 1
        res *= 2
        break
for i in query:
    x = f(i)
    while x > 1:
        tmp = sieve[x]
        if tmp in y:
            y.remove(tmp)
            cnt -= 1
        else:
            res *= pow(d[tmp] + 1, -1, M)
            res %= M
        while x % tmp == 0:
            x //= tmp
            d[tmp] += 1
        if (d[tmp] + 1) % M == 0:
            y.add(tmp)
            cnt += 1
        else:
            res *= d[tmp] + 1
            res %= M
    if cnt == 0:
        print(res)
    else:
        print(0)

Solution (Python):
import sys
input = sys.stdin.readline
(x, q, Mod) = map(int, input().split())
a = list(map(int, input().split()))
Mx = 2 * 10 ** 6 + 1
prime = [1] * Mx
for i in range(2, Mx):
    if prime[i] == 1:
        for j in range(i, Mx, i):
            prime[j] = i
cmbinv = [1, 1]
for i in range(2, min(Mx, Mod)):
    cmbinv.append(-cmbinv[Mod % i] * (Mod // i) % Mod)
from collections import defaultdict
d = defaultdict(int)
ans = 1
e = 0
while x % 2 == 0:
    x //= 2
for i in range(q):
    while a[i] % 2 == 0:
        a[i] //= 2

def mul(x):
    global ans, e
    if x % Mod == 0:
        e += 1
    else:
        ans = ans * x % Mod

def div(x):
    global ans, e
    if x % Mod == 0:
        e -= 1
    else:
        ans = ans * cmbinv[x % Mod] % Mod
p = 3
while p * p <= x:
    while x % p == 0:
        d[p] += 1
        mul(d[p] + 1)
        div(d[p])
        x //= p
    p += 1
if x != 1:
    d[x] += 1
    mul(d[x] + 1)
    div(d[x])
for num in a:
    while prime[num] != 1:
        d[prime[num]] += 1
        mul(d[prime[num]] + 1)
        div(d[prime[num]])
        num //= prime[num]
    print(ans if e == 0 else 0)