ABC342 D問題の解説(Python)

はじめに

この記事では、ABC342のD問題を解説していきます。

ABC(AtCoder Beginner Contest)とは、AtCoderが開催している、競技プログラミングコンテストです。

ABC342 D – Square Pair

問題

問題

長さNの非負整数列 \(A=(A_1, …, A_N)\) が与えられます。積が平方数となる2数のインデックスの組の個数を数える問題です。

制約

  • \(2 \leqq N \leqq 2×10^5 \)
  • \(0 \leqq A_i \leqq 2×10^5 \)

思考の筋道

この問題において、0は特別な数です。0はもう片方の数が何であっても、積が0で平方数になるからですね。そのため、まずは0以外の数について考えてみましょう。

0以外の数の検討

0以外の数については素因数分解を行います。2つの数の積が平方数になるのは、積の素因数の指数が偶数になるときです。つまり、かける前の2つの数について、指数が奇数の素因数が完全に一致するときですね。少しややこしいので例を見てみましょう。

具体例:2と72

2は、指数が奇数の素因数は2のみ。
72(=2^3×3^2)も、指数が奇数の素因数は2のみ。
この2つの数は、指数が奇数の素因数が一致します。かけると 2^4×3^2 となり、すべての素因数の指数が偶数となります。そのため、平方数です。

なお、2つの数について、指数が奇数の素因数が完全に一致するかどうかは、指数が奇数の素因数の積が一致するかどうかで調べることができます。

0を含む場合の検討

次は0を含むケースを考えましょう。はじめに述べた通り、0はもう片方の数が何であっても、積が0で平方数になります。しかし、0が複数ある場合は、0×0をダブルカウントしないように注意が必要です。

具体例:A=(0, 0, 2, 4, 8, 72)
  • 1つ目の0について
    0はもう片方の数が何であっても平方数になるので、自分を除いた5だけカウントプラス
  • 2つ目の0について
    先ほど「1つ目の0×2つ目の0」のケースは数えたので、そのケースと自分を除いた4だけカウントプラス
  • 残りの2, 4, 8, 72について
    この中で指数が奇数の素因数が完全に一致するのは、2, 8, 72の三つ。この中から二つを選べば積が平方数になるので、\({}_3 \mathrm{ C }_2=3 \) だけカウントプラス

よって答えは、5+4+3=12となる。

整数問題で素因数に着目する問題はしばしば出題されます。

下記のコードでは、factorization関数で素因数分解をしています。素因数分解のコードはいつでも取り出して使えるようにしておくとよいでしょう。

コード

N = int(input())
A = list(map(int, input().split()))

def factorization(n):
    arr = []
    temp = n
    for i in range(2, int(-(-n ** 0.5 // 1)) + 1):
        if temp % i == 0:
            cnt = 0
            while temp % i == 0:
                cnt += 1
                temp //= i
            arr.append([i, cnt])
    if temp != 1:
        arr.append([temp, 1])
    return arr

def f(a):
    fac = factorization(a)
    res = 1
    for k, n in fac:
        if n % 2:
            res *= k
    return res

d = dict()
ans = 0
zero_count = 0

for num in A:
    if num == 0:
        ans += N - 1 - zero_count
        zero_count += 1
    else:
        s = f(num)
        if s in d:
            d[s] += 1
        else:
            d[s] = 1

for a in d:
    if d[a] >= 2:
        ans += (d[a] * (d[a] - 1)) // 2

print(ans)

以上、ABC342のD問題の解説でした!

では、またね。

リンク