Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

求和意义和性质

当一个算法包含循环结构, 例如 whilefor, 我们常常可以把它的运行时间表示为每次迭代所花时间之和. 因此, 求和不仅是数学中的基础工具, 也是算法分析中最常见的表达形式之一.

求和符号

在数学中, 求和符号写作 读作 sigma(西格玛). 它表示一系列数值的累加.1

一个典型写法是:

其中:

  • 是起始下标, 表示从第 项开始求和;
  • 是终止下标, 表示求到第 项;
  • 是被累加的项.

等价地,

如果把上限扩展到无穷大, 就得到无穷级数:2

线性性质

求和最重要的性质之一是线性.

对于任意数列 , 有:

对于常数 , 有:

合并起来, 可写成:

这一性质非常适合用于拆分复杂求和式, 例如:

常见求和公式

等差和

最经典的求和是自然数和:

用高斯配对法可得:

其增长阶为:

平方和

平方和公式为:

其增长阶为:

立方和

立方和公式为:

其增长阶为:

几何级数

几何级数在算法分析中也极其常见:

时, 有:

如果 , 则无穷几何级数收敛:

望远镜求和

有些求和式可以通过相邻项抵消, 形成“望远镜”效果.

例如:

展开后大部分项会抵消, 最后只剩首尾项:

这类技巧常用于推导闭式公式, 也常用于证明一些求和恒等式.

与算法分析的关系

很多算法的运行时间都能写成求和形式. 例如:

  • 线性扫描:

  • 双重循环:

  • 嵌套循环但内层次数逐渐变化:

  • 分治递归展开后常得到几何级数或混合级数.

因此, 掌握求和不仅是为了做数学题, 更是为了把算法时间复杂度算出来.

编程中的求和

Rust 中可以直接利用迭代器来实现求和.

通用求和

pub fn sigma_sum<T, F>(start: i32, end: i32, f: F) -> T
where
    T: std::iter::Sum,
    F: Fn(i32) -> T,
{
    (start..=end).map(f).sum()
}

// 例: 计算 1^2 + 2^2 + ... + 5^2
let ans: i32 = sigma_sum(1, 5, |x| x * x);

等差和的 O(1) 公式

对于 1 + 2 + ... + n 这类等差和, 可以直接使用公式而不是循环累加:

pub fn gauss_sum(start: i64, end: i64) -> i64 {
    let len = end - start + 1;
    let sum = start + end;

    if len % 2 == 0 {
        (len / 2) * sum
    } else {
        len * (sum / 2)
    }
}

这样做把时间复杂度从 \Theta(n) 降到了 \Theta(1).


  1. 若级数极限存在, 则称其收敛; 否则称其发散.

  2. 对于收敛级数, 求和顺序并不总能随意交换; 若级数绝对收敛, 则可交换求和顺序.