今回は paiza の「規則的な数列の和」の問題に挑戦!
問題概要
- 無限に続く数列A
A = [1, 0, -1, 1, 0, -1, ...]
- 整数
N,Kが与えられ、 - 数列A の
N要素目からK要素目までの和 を求める - 要素番号は 1 始まり
入力
- 1 行:整数
N, K - 条件:1 ≤
N≤K≤ 10^12
出力
- 区間 [
N,K] の要素の総和を 1 行で出力
入力例:
1 1000000000000
出力例:
1
✅OK例:
const rl = require('readline').createInterface({
input: process.stdin,
output: process.stdout
});
rl.on('line', (line) => {
const [n, k] = line.split(' ').map(Number);
let result = 0;
if (n % 3 === 0) {
if (k % 3 === 0) {
result = -1;
}
} else if (n % 3 === 1) {
if (k % 3 !== 0) {
result = 1;
}
} else { // n % 3 === 2
if (k % 3 === 0) {
result = -1;
}
}
console.log(result);
rl.close();
});
🔍 コード全体の流れ
- 標準入力から
NとKを受け取る - 数列
[1, 0, -1]が 3 個周期で繰り返されることを利用する -
N % 3とK % 3の組み合わせだけで - 区間
N〜Kの和が-1/0/1のどれかに決まる - 条件分岐でその値を直接求めて出力する
※ NとKは1-indexedで与えられる
行ごとの処理の流れ
-
readlineを使って 1 行入力を受け取る - 入力された文字列を分割して
n, kに変換 - 答え用の変数
resultを0で初期化
条件分岐の意味
① n % 3 === 0 の場合
-
区間の開始位置が
-1の位置 -
k % 3 === 0なら
→ 余分に-1が 1 回多く含まれる
→result = -1
② n % 3 === 1 の場合
- 区間の開始位置が
1の位置 -
k % 3 !== 0(区間が0で終わらない)なら
→1が 1 回多く含まれる
→result = 1
③ n % 3 === 2 の場合
- 区間の開始位置が
0の位置 -
k % 3 === 0なら
→-1が 1 回多く含まれる
→result = -1
最後に
- 計算結果
resultを出力 -
rl.close()で入力処理を終了
💡 この解法のポイント
- 実際に足し算は一切していない
- 「3 個で和が 0」という性質を使い
- 余る 1 要素だけを見て答えを決めている
📝まとめ
この問題で起きていること
- 数列は
[1, 0, -1]の繰り返し - 3 個そろうと必ず和が 0
だから
👉 N〜K のほとんどは打ち消し合う
👉 端っこに余った 1 要素だけが答えを決める
なぜ「N % 3 と K % 3 だけ」で決まる?
-
Nがどの値(1/0/-1)から始まるか -
Kがどこで終わるか
この 始点と終点のズレだけで、「余る 1 個」が
1-1- 何も余らない(
0)
のどれかに決まるから。
条件分岐を「数列の位置」で見る
n % 3 === 0
→ 位置: -1 からスタート
k も %3==0 で終わると
→ -1 が 1 回多く残る
→ -1
n % 3 === 1
→ 位置: 1 からスタート
k が 0 で終わらなければ
→ 1 が 1 回多く残る
→ +1
n % 3 === 2
→ 位置: 0 からスタート
k が %3==0 なら
→ -1 が 1 回余る
→ -1
なぜ result = 0 が初期値?
条件に当てはまらない場合は
👉 完全に 3 個セットで消える
つまり何も余らない
だから 0 のままで正解
一言で言うと
「3 個で 0 になる数列だから、
全体は無視して "余る 1 個" だけを見る」