奇数求和

GitHub跳转原题关系图返回列表

端点按奇偶收缩到首末奇数后套等差数列公式,O(1) 算闭区间奇数和;区间内无奇数时项数自然为 0,无需分支。

OJ: roj

题目 ID: 1065

难度:入门

标签:循环结构等差数列位运算Python

创建: 2026-09-29 16:58

更新: 2026-10-04 23:57

题目描述

给定两个数 m,nm, n(0⩽m⩽n⩽3000 \leqslant m \leqslant n \leqslant 300),求闭区间 [m,n][m, n] 内所有奇数之和。输入一行 mm nn(一个空格分开),输出一行一个整数表示答案。样例输入 7 15,输出 55(即 7+9+11+13+157+9+11+13+15)。

思路

把端点按奇偶挪到区间内首末奇数,再套等差数列求和公式 S=(a1+ak)k/2S=(a_1+a_k)k/2;无奇数时项数公式自然得 0,免分支。

参考代码

Python 版:

python
#!/usr/bin/env python3
# Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
# rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
# rainboy的学习导航网站: https://idx.roj.ac.cn
# create_at: 2026-09-29 16:58
# update_at: 2026-09-29 16:58

import sys


def solve() -> None:
    m, n = map(int, sys.stdin.buffer.read().split())
    first = m if m & 1 else m + 1   # 区间内第一个奇数:m 为偶数则右移一位
    last = n if n & 1 else n - 1     # 区间内最后一个奇数:n 为偶数则左移一位
    count = (last - first) // 2 + 1  # 奇数个数:等差数列项数,可能算出 0 项
    print((first + last) * count // 2)  # 等差数列求和公式;两因子恒一偶,整除无损


if __name__ == "__main__":
    solve()

C++ 版(同一算法):

cpp
/**
 * Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
 * rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
 * rainboy的学习导航网站: https://idx.roj.ac.cn
 * create_at: 2026-10-04 23:57
 * update_at: 2026-10-04 23:57
 */
// main.cpp:闭区间 [m, n] 内奇数求和。
// 关键观察:[m,n] 内的奇数构成公差为 2 的等差数列,故可用闭式求和。
// 端点收缩:m 偶则 +1 得首项,n 偶则 -1 得末项;其余原样保留。

#include <cstdio>

typedef long long ll;

ll m, n;       // 输入的两个端点
ll first;      // 区间内第一个奇数(首项)
ll last;       // 区间内最后一个奇数(末项)
ll cnt;        // 奇数项数,等差数列项数;区间内无奇数时自然为 0
ll sum;        // 等差数列求和结果

int main() {
    scanf("%lld %lld", &m, &n);
    first = (m & 1) ? m : m + 1;          // m 偶则右移一位得到第一个奇数
    last  = (n & 1) ? n : n - 1;          // n 偶则左移一位得到最后一个奇数
    cnt   = (last - first) / 2 + 1;       // 项数公式;(last<first) 时也为 0
    sum   = (first + last) * cnt / 2;     // 等差数列求和:first+last 恒偶,整除无损
    printf("%lld\n", sum);
    return 0;
}