競プロ備忘録

競プロerの備忘録

ABC206E - Divide Both

計算量がよくわかりませんが、なぜかACできてしまったので書きます。(公式解説を見たら同じような解法が載ってました)

解法

問題の条件を言い換える。
まず、条件を満たす x, yの組み合わせは、( x = yであるような場合をさておくと)対称になるので、 x yの関係はとりあえず x \le yとしてよい。
さらに、 x / gcd(x, y) \neq 1から、 x \neq gcd(x, y)でなく、したがって x \neq yであるので、条件は x \lt yとすることができる。この条件下の解が出れば、これを2倍することで元の問題の解になる。

また、 x \neq yから、 y = gcd(x, y)となることはないので、条件のうち、 y / gcd(x, y) \neq 1は削ることができる。
したがって、問題の条件は gcd(x, y) \neq 1かつ x / gcd(x, y) \neq 1になる。
さらに言い換えると、 gcd(x, y) = 1または x / gcd(x, y) = 1であるような (x, y)の組み合わせが求まれば、全体からこれを引けば解がでるので、以降これを求めることとする。

これを求めるには、 xを範囲中全探索し、 xと互いに素な y ( gcd(x, y) = 1から)、あるいは xの倍数である y ( x / gcd(x, y) = 1から)、の2つを求めて足しこめばよい。
後者については簡単に求められる。( R / x - 1です)
前者については、 xの約数の倍数でないような数を求めればよいが、実際には約数の倍数ではなく、素因数の倍数で十分である。 xの素因数は 2 * 3 * 5 * 7 * 11 * 13 * 17  \lt 10 ^ 6 \lt 2 * 3 * 5 * 7 * 11 * 13 * 17 * 19であることから最大でも 7個程度なので、包除原理を用いることで、区間 (x, R]の中で xの素因数の倍数でない数を求めることができる。

これらを足し込んだ結果は、 x \lt yの条件において、元の問題で与えられた条件を満たさない場合の数であるので、 x, yのすべての組み合わせである (R - L + 1) ^ 2からこれを 2倍して引き、さらに x = yの場合は元の問題の条件を満たさない( gcd(x, y)で割ると x, yともに 1となる)ため、 R - L + 1を引いた数が最終的な解となる。

計算量

これが私にはわかりません…
 L = 1, R = 10 ^ 6の場合が最悪の場合ですが、かなり高速に動作します。

直感的には、だいたい多くの数の素因数はせいぜい 4, 5個くらいだろう、みたいなテキトーな見積もりから、だったら最悪でも 10 ^ 6 * 10から 10 ^ 6 * 20程度になって通るだろう、という感覚で投げたら通りました。良くないですね…

コードは以下の通り。

Submission #35216632 - AtCoder Beginner Contest 206(Sponsored by Panasonic)