A - Two Arithmetic Progressions Editorial by evima
Solution 1
Using the Euclidean algorithm, the problem can be reduced to the case \(C=0\).
while C != 0:
int k = floor(A / C)
A = A - k * C
B = B - k * D
swap(A, C)
swap(B, D)
Let the values of \(A,B,C,D\) after this process be \(A',B',C'(=0),D'\). Then the answer is \(\displaystyle \sum_{i=1}^N \gcd(A'i+B',|D'|)\). Here, \(|D'|\leq 10^8\) (because \(|AD-BC|\) is always constant).
When \(D'=0\), the problem is straightforward.
When \(D'\neq 0\), for each positive divisor \(m\) of \(D'\), we can find the number of \(i\,(1\leq i\leq N)\) such that \(A'i+B'\) is a multiple of \(m\) by solving a linear Diophantine equation. Then, by Moebius inversion over divisors, we can find the number of \(m\) such that \(\gcd(Ai+B,|D'|)=m\).
The number of divisors of an integer up to \(10^8\) is at most \(768\), so even taking quadratic time for the Moebius inversion is fast enough.
Solution 2
Because \(C(Ai+B)-A(Ci+D)=(CB-AD)\), the greatest common divisor is a divisor of \(|CB-AD|\). When \(CB-AD=0\), the problem is straightforward.
For each divisor \(m\) of \(|CB-AD|\), the condition on \(i\) such that both \(Ai+B\) and \(Ci+D\) are multiples of \(m\) can be found by repeatedly solving linear Diophantine equations. The rest follows as in Solution 1.
Sample implementation of Solution 1
from atcoder.math import inv_mod
from math import gcd
def divisors(n):
lower, upper = [], []
i = 1
while i * i <= n:
if n % i == 0:
lower.append(i)
if i * i != n:
upper.append(n // i)
i += 1
return lower + upper[::-1]
mod = 998244353
def solve():
n, A, B, C, D = map(int, input().split())
B += A
D += C
while C != 0:
k = A // C
A -= k * C
B -= k * D
A, B, C, D = C, D, A, B
if D == 0:
print((n * (n - 1) // 2 * A + B * n) % mod)
return
divs = divisors(abs(D))
sz = len(divs)
cnt = [0] * sz
ans = 0
for i in range(sz - 1, -1, -1):
m = divs[i]
g = gcd(A, m)
if B % g == 0:
p, q, r = A // g, B // g, m // g
mn = (-q * inv_mod(p, r)) % r
cnt[i] = max(0, (n - 1 - mn) // r + 1)
for j in range(i + 1, sz):
if divs[j] % m == 0:
cnt[i] -= cnt[j]
ans += m * cnt[i]
print(ans % mod)
for _ in range(int(input())):
solve()
posted:
last update: