Official

D - Staircase Sequences Editorial by tatyam


数列 \([A, A + 1, \dots, B - 1, B]\) の総和は、各要素に \([B, B-1, \dots, A + 1, A]\) を足すことを考えると、 \(\dfrac{(A + B)(B - A + 1)}{2}\) です。

よって、この問題は

\[ (A + B)(B - A + 1) = 2N \quad (A ≤ B) \]

の整数解の個数を求める問題に言い換えることができます。
このとき、 \(A + B, B - A + 1\) はどちらも正の整数であるため、どちらも \(2N\) の約数になります。
そこで、 \(2N=x \times y\) と正の整数 \(2\) つに分解する方法を列挙し、

\[ \begin{cases} A + B = x\\ B - A + 1 = y\\ \end{cases} \]

を解いて整数解の個数を数えます。
この解は \(x\)\(y\) の偶奇が異なるとき、
\(A = (x - y + 1)/2,\ B = (x + y - 1)/2\)
で、 \(x\)\(y\) の偶奇が同じとき整数解は存在しません。

これより、 \(2N\) を偶奇の異なる正の整数 \(2\) つに分解する方法の数がこの問題の答えになります。
\(2N\)約数列挙 は計算量 \(O(\sqrt N)\) でできるため、 \(O(\sqrt N)\) でこの問題を解くことができます。

また、 \(2N\)\(2\) を素因数に \(1\) つ以上含むため、\(x,y\) のどちらか片方しか \(2\) を素因数に持たないことを考えると、
\(M=\) ( \(N\)\(2\) で割り切れなくなるまで割った数 ) として、 ( \(M\) の約数の個数 )\({}\times 2\) がこの問題の答えになります。

回答例 (C++)

#include <iostream>
#include <cmath>
using namespace std;
using ll = int64_t;

int main(){
    ll N;
    cin >> N;
    while(N % 2 == 0) N /= 2;
    ll sq = sqrt(N), ans = 0;
    for(ll i = 1; i <= sq; i++) if(N % i == 0) ans += 2;
    if(sq * sq == N) ans--;
    cout << ans * 2 << endl;
}

回答例 (Python)

N = int(input())
while N % 2 == 0:
    N //= 2
sq = int(N ** 0.5)
ans = sum(N % i == 0 for i in range(1, sq + 1)) * 2 - (sq * sq == N)
print(ans * 2)

posted:
last update: