条件を上手に言い換えよう!
問題概要
個の整数 が与えられる。
- が平方数
という条件を満たすような組 の個数を求めよ。
制約
考えたこと
これは「条件の言い換え」を頑張る問題。「 が平方数」という条件を扱いやすいように言い換えよう。これがちょっと難しい。
個人的に思ったのは、平方根を持ち出すとわかりやすかった(ただし、、 の部分は別に考えることとして、 は 1 以上とする)。
- が平方数であるとは、 が整数であることである
- そのことは、 をそれぞれ簡単にしたときに、√ の中身が一致することと同値である
たとえば、 をかけると となって平方数となるが、これは次のように解釈できる。
- である
- である
- これらは の部分が一致しているから、かけると整数になる
この言い換えさえできれば、あとは簡単だ。次のように問題は言い換えられる。
をそれぞれ簡単にしたときの √ の中身を とする。
という条件を満たすような組 の個数を求めよ。
これは、map
などを使って集計処理することで、容易に答えられる。
なお、0 は例外処理する必要がある。0 に何をかけても 0 であって、これは平方数であるからだ。
全体として、 の最大値を として、計算量は となる。
コード
#include <bits/stdc++.h> using namespace std; const int MAX = 210000; int main() { long long N, A; cin >> N; vector<long long> nums(MAX, 0); for (int i = 0; i < N; i++) { cin >> A; for (long long j = 2; j * j <= A; j++) { while (A % (j * j) == 0) { A /= j * j; } } nums[A]++; } // (0, 他の数) の組の個数 long long res = N * (N - 1) / 2 - (N - nums[0]) * (N - nums[0] - 1) / 2; // 0 を含まない組の個数 for (long long val = 1; val < MAX; val++) { res += nums[val] * (nums[val] - 1) / 2; } cout << res << endl; }