Skip to content

笔记

数论

基于质因数的最小公倍数求解

采用两两合并的形式,根据最小公倍数的性质可知:$n$ 个数的最小公倍数是这些数中每个数进行质因数分解后,所有的质因数按对应次数累乘的最终结果。

  • 预处理:根据题目给的数据范围进行质数打表。本题题目范围是 $1e9$,因此需要计算 $sqrt(1e9)$ 范围内的质数。
  • 根据质数表找检查每个数的质因数和其对应的次数
  • 如果一个质因数在不同的数中都有分解出,则次数取高者。
  • 需要注意如果遍历完所有表内质数后,该数还有剩余,则它是一个在 $sqrt(1e9)$ 范围外的质数,需要单独记录。
  • 基于快速幂求质因数表的乘积和,注意取模。

基于欧几里得算法的最大公约数求解

即辗转相除法,快速求最大公约数。

已知 $a, b$ 两数,求两者最大公约数,用其中大数除以小数,取余数;对于小数和余数,用大数除以小数,取余数……直到余数为 0,此时的除数就是两者的最大公约数。

基于数学方法的回文数判断

对于 int 型的数字串,如果转换为字符串再判断会有频繁的栈开销和较大的常数,因此可以考虑通过提取 + 翻转原数(除10取模,模*10 ,直到中间位)的后半段,并判断翻转后的数字串是否和前半段相等来快速推断。

组合数计算

从 $m$ 个不同元素中不重复、不考虑顺序地选出 $n$ 个的方式总数:

$$C(m, n) = \binom{m}{n} = \frac{m!}{n!(m-n)!}$$

如果需要去重需要在计算前:

std::vector<int> A = {1, 2, 2, 3};
std::set<int> unique_set(A.begin(), A.end()); // 自动去重
std::vector<int> unique_vec(unique_set.begin(), unique_set.end());

前缀和/差分

需要尤其注意边界检查。

等差数列一维差分

已知数组arr,对其进行$k$次操作,每次操作选取左右两个端点,给定一个相同长度的等差数列[s,e,d]表示数列首尾和公差,一一对应加在选取的区间上,求多次操作后的结果。

本质上是两次一维差分,和一维差分相同,不支持边查边改;在每次操作的预处理中和一维差分有所区别,执行以下四步:

  • arr[l]+=s
  • arr[l+1]+=d-s
  • arr[r+1]-=d+e
  • arr[r+2]+=e

二维差分

在遇到二维矩阵+区域覆盖时考虑二维差分,总体思路是对数据进行预处理后进行二维前缀和,得到的就是每个元素的变化值。

给定矩阵$matrix$,进行$k$次操作,每次操作对以$[lx,ly]$和 $[rx,ry]$分别为左上顶点和右下顶点的矩形区域中的每个值加$v$,则进行以下预处理:

  • pre[lx][ly]+=v
  • pre[lx][ry+1]-=v
  • pre[rx+1][ly]-=v
  • pre[rx+1][ry+1]+=v