Official
C - 最強の結束 / The Strongest Unity Editorial
by
C - 最強の結束 / The Strongest Unity Editorial
by
harurun4635
以下 \(M = \max(A)\) とします。
まず \(G\) を求めましょう。しかし、すべての部分集合に対して求めるのは現実的ではありません。ここで
- \(S\) の要素がすべて \(G\) で割り切れる \(\iff\) ある集合 \(S\) の \(\gcd\) が \(G\) の倍数である
が成り立つことを利用します。(証明はそこまで難しくないため、省略させてください)
つまり、ある \(g\) の倍数が \(2\) つ以上存在すれば、それを選んで \(S\) とすることで \(\gcd\) を \(g\) の倍数とできます。そして、このような \(g\) としてありうる最大値を求めれば、それが \(G\) であることもわかります。
これは、あらかじめ頻度列をつくっておけば、愚直に \(g\) の倍数をすべて舐めても、調和級数で抑えられて \(O(M \log M)\) で求めることができます。
とかなんとかいいましたが、実は答えは \(N-2\) です。
つまり、 \(G\) の倍数が \(3\) つ以上存在しても、そこから(適切にではなく)適当に \(2\) つ選べば、必ず \(\gcd\) は \(G\) になることが示せます。
上の議論から分かるとおり、一般的には「 \(\gcd\) が \(G\) の集合があるとき、その部分集合の \(\gcd\) は \(G\) の倍数である」ことまでしかわかりません。しかし、今回は \(G\) が \(\gcd\) の最大値ですから \(G\) より大きくなることはないため、 \(G\) 以外の値になることはありません。
実装例
n = int(input())
print(n - 2)
posted:
last update: