解説
Sx(N) の個数 ∣Sx(N)∣ を考えてみましょう。整数 i について、j=1∑ij=2i(i+1) より、この値が x の倍数であるためには i(i+1) が 2x の倍数、つまりi(i+1)≡0mod2x となれば良いです。
では、このような i を探してみます。 ここで、唐突に 2x を素因数分解し、その結果を 2x=k=1∏Kpkek とします。このとき、任意の k について、
i(i+1)≡0⟷i≡0,−1modpkek が成り立ちます。(i と i+1 は互いに素であることから)
一方で、i(i+1)≡0mod2x⟷∀k,i(i+1)≡0modpkek が成り立つため(検証は追記にて)、
それぞれの k について i≡0,−1modpkek が成り立てばよいと分かります。このような条件を満たす i は、各 k について i≡0 と i≡−1 (modpkek) の 2 通りから選ぶので、合計で 2K 通りです。これら 2K 通りの imod2x を列挙し、列挙した i それぞれについて 1 から N までの中に2x で割ったあまりが i となるような整数が何個あるかを求めることで ∣Sx(N)∣ を求めることができます。
計算量について考えます。まず、素因数分解は試し割り法を用いて O(a) です。
2K 通りの i の値の列挙に関して、各 i の構築において拡張ユークリッドの互除法を用いた中国剰余定理に O(Kloga) かかるため、列挙全体で O(2KKloga) かかります。ここで、 K の上限は、2×a までの整数のうち、最も多くの素因数をもつ整数における素因数の個数の上限であり、Sp=2⋅3⋅5⋅7⋅11⋅13⋅17⋅19⋅23⋅29⋅31<2×1012<Sp×37 から K≤11 であるので、問題ありません。よって全体として O(a+2KKloga) となり、これは十分高速です。
追記
- i(i+1)≡0mod2x⟷∀k,i(i+1)≡0modpkek
まず ⟶ は明らかです。i(i+1) が 2x の倍数であるとき、任意の k について pkek は 2x の約数より、i(i+1) は pkek の倍数となります。
また、⟵ も明らかです。任意の k について i(i+1) を pkek が割り切れるとき、pkek 同士は互いに素であるので、それらの積である 2x は i(i+1) で割り切ることができます。