GCD of Contiguous Subsequence

2 secs 1024 MB
take44444's icon take44444

22整数におけるGCDは,結合律を満たします.また,多くの言語でGCDの単位元は 00 とされており,整数集合におけるGCDはモノイドであると言えます.従って,セグメント木を用いて,指定区間のGCDは,O(log(N)log(A))\mathrm{O}(\log (N) \log (A)) で高速に計算可能です.

また,G(l,r)=gcd(Al,Al+1,Al+2,Ar)G(l, r) = \gcd(A_l, A_{l+1}, A_{l+2}, \dots A_{r}) とすると,ll を固定したとき,G(l,r)G(l, r)rr について明らかに広義単調減少です.
従って,数列AAの区間における左端 ll を固定したとき,G(l,r)MG(l, r) \geq M を満たす最大の rrr1r_1G(l,r)>MG(l, r) \gt M を満たす最大の rrr2r_2 として,r1r2r_1-r_2 個が G(l,r)=MG(l, r) = M を満たします.
よって,11 以上 NN 以下の ll について上の値を二分探索とセグメント木を用いて O(log2(N)×log(A))\mathrm{O}(\log^2 (N) \times \log (A)) で求めることができるため,全体の計算量は O(N×log2(N)log(A))\mathrm{O}(N \times \log^2 (N) \log (A)) となりますが,セグメント木上で直接二分探索を行うことで,さらに計算量を O(N×log(N)log(A))\mathrm{O}(N \times \log (N) \log (A)) に落とすことができます.

コード例(C++)