危うく平方分割するところだった……
Aiを書き換えるとき、最大公約数は高々gcd(A1,...,Ai−1,Ai+1,...,AN)であり、実際、Aiをgcd(A1,...,Ai−1,Ai+1,...,AN)に書き換えればこの値にできる。したがって、G(i):=gcd(A1,...,Ai−1,Ai+1,...,AN)とすると、G(i)の最大値が答えである。
L(i):=gcd(A1,...,Ai−1), R(i)=gcd(Ai+1,...,AN)とするとG(i)は
G(i)=gcd(L(i),R(i))
で計算できるので、
L(i):=gcd(L(i−1),Ai−1)R(i):=gcd(R(i+1),Ai+1)
を利用して先にL(i), R(i)のテーブルを作っておけばよい。
あと、今まで意識したことがなかったけど、gcd
の単位元として0が使えるという理解を得た。
別解とか
これはうまい考え方だと思った。……けど、最初の2つの数の約数から素朴に調べる方針だと、例えば
100000
735134400 698377680 735134400 ... (99996個連続) ... 735134400 1 1
みたいな入力でけっこう時間が怪しい。とはいっても、高々2×108程度のループですむので、C++なら大丈夫だろうな。
Divisor function d(n)の上限を見る限り、計算量は任意のϵ>0に対してo(N(maxAi)ϵ)と評価できるようだが、漸近的な評価があまり役に立たない例にも見える。supi≤nd(i)の具体的な値を覚えておいたほうが良さそう。
参考: https://gist.github.com/dario2994/fb4713f252ca86c1254d