コンテンツにスキップ

素因数分解

タグ「素因数分解」の記事 1 件

Blitz Round #25 C - Root Value

正の整数 xx に対して、xm\sqrt[m]{x} が自然数になるような最大の mm を f(x)f(x) とします。

長さ nn の数列 a1,…,ana_1, \ldots, a_n (2≤ai≤2002 \le a_i \le 200) と qq 個のクエリ (l,r)(l, r) が与えられるので、各クエリについて

f(∏i=lrai)f\left(\prod_{i=l}^{r} a_i\right)

を求める問題です。

  • 1≤n,q≤2⋅1051 \le n, q \le 2 \cdot 10^5、テストケースの nn の総和と qq の総和はそれぞれ 2⋅1052 \cdot 10^5 以下

正確な問題文は元の問題ページを見てください。

xx を素因数分解して x=p1e1p2e2⋯pkekx = p_1^{e_1} p_2^{e_2} \cdots p_k^{e_k} とすると、xm\sqrt[m]{x} が整数になるのは、すべての指数 eje_j が mm の倍数のときです。したがって

f(x)=gcd⁡(e1,e2,…,ek)f(x) = \gcd(e_1, e_2, \ldots, e_k)

です。ai≥2a_i \ge 2 なので、積は 22 以上になり、指数のどれかは正になります。

積をそのまま計算すると巨大になりますが、指数だけを見れば足し算になります。ai≤200a_i \le 200 なので、現れる素数は 200200 以下の 4646 個だけです。各素数について指数の累積和を持っておけば、区間 [l,r][l, r] での各素数の指数は差を取るだけで求まり、その gcd⁡\gcd が答えです。

aia_i の上限を AA (=200= 200)、AA 以下の素数の個数を π(A)\pi(A) (=46= 46) とすると、計算量は O((n+q) π(A))O((n + q)\,\pi(A)) です。

Python
from math import gcd
prime = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199]
for _ in range(int(input())):
N, Q = map(int, input().split())
A = list(map(int, input().split()))
acc = [[0] * len(prime)]
for a in A:
t = acc[-1].copy()
for i, p in enumerate(prime):
while a % p == 0:
t[i] += 1
a //= p
acc.append(t)
for _ in range(Q):
l, r = map(int, input().split())
l -= 1
ans = 0
for i in range(len(prime)):
ans = gcd(ans, acc[r][i] - acc[l][i])
print(ans)