数学小结
1. 有时有用的数学小知识
- (a cdot d equiv b cdot d (mod c) Leftrightarrow a equiv b (mod frac{c}{(d, c)}))
- 完系的每个元素同时乘上一个与模数互素的数,仍然是完系
- 完系的每个元素同时加上一个数,仍然是完系
- 缩系的每个元素同时乘上一个与模数互素的数,仍然是缩系
- 欧拉定理: (V + F = E + 2)
2. 欧几里得算法
化式子的时候,显然 ((ad,bd)=dcdot(a,b)) 。
A. 贝祖定理(裴蜀定理)
关于 (x,y) 的方程 (ax+by = (a,b)) 有解。推广到 (n) 元方程也成立。
因此, (ax+by=c Leftrightarrow c|(a,b)) 。
由此,还有一个推论:
只要 (b) 的系数还是 (1) , gcd 就不变。证明:
设 (a'cdot (a,b)=a, b'cdot (a,b)=b) 则 ((a',b')=1) 。
由裴蜀定理, (a'x+b'y=1) 有解。
设 (m=a',n=pm b' pm ka') , 凑系数得到 (mX+nY=1) 有解,为 (X=xpm ky, Y=y) 。
所以 ((m,n)|1Rightarrow(m,n)=1) ,得到:
B. 欧几里得算法
求解两个数的最大公约数。
C. 扩展欧几里得算法
要求关于 (x,y) 的不定方程( (a,b) 是常数 ):
如果可以求得:
移项即求得:
由这个式子与原式的关系,可以得到:
3. 中国剩余定理
A. 中国剩余定理
B. 扩展中国剩余定理
4. BSGS
5. 多项式
A. 前置知识
线性求逆
法一, Inv[i] = (P - P / i) * Inv[P % i]
,原理 [数论]线性求所有逆元的方法 - Miskcoo's Space 。
法二,预处理阶乘,然后费马小定理算下最大的阶乘逆元, J_inv[i] = J_inv[i + 1] * (i + 1)
,之后 Inv[i] = J_inv[i] * J[i - 1]
。
高斯消元
其他
- 数论阶(最小的正整数 (n) ,使得 (a^n equiv 1) )
- 原根
- 完全剩余系(完系) & 简化剩余系(缩系)
- 复数(数学选修 2-2 )
- 导数(数学选修 2-2 )
- 微积分(数学选修 2-2 )
B. 快速傅里叶变换 & 快速数论变换
卷积
不严谨地说,卷积大概就是形如 (c_i=sum_{j=0}^{i}a_jcdot b_{i-j}) 的东西。
注意不要思维僵化, (c_{i}=sum_{j=i}^{n}a_{j-i}cdot b_{j}) 不是卷积,但是设 (x_{n-j}=b_j) 之后,它就是卷积,不过卷起来之后的系数与 (c) 正好相反而已。
如果不能意会,那么更严谨一点,设 (y_{i}=c_{n-i}) 则:
继续不严谨地说,只要右边的两个下标和(或者差)只与左边下标有关,就可以卷积。是差的时候需要翻转系数。
系数表示法卷积时间复杂度太高,所以傅里叶变换成点值表示法,卷积之后再逆变换回系数表示法。 (O(n log n)) 。
变换
两者都利用了不同自变量对应的函数值之间有简单关系来减少计算量。
FFT 的不同自变量是复数 (e^{frac{2pi}{n}i}) 。注意 (e^{ heta i} = cos heta + i cdot sin heta) ,把 (e^ heta,sin,cos) 分别泰勒展开就可以证明。
NTT 的不同自变量是原根 (g) 的若干次幂 (g^{frac{p}{n}cdot k} (kin [0,p)) ,它们恰好构成一个完系。
如何找原根呢?
当然是背下来几个常用的啊。
不过一定找 (x) 的原根也有方法。只有 (2,4,p^n,2p^n) ((p) 是素数)有原根,并且数量是 (phi(phi(x))) 。可以证明(这次不是口胡) (g|phi(x)) ,枚举。
据说还有这样一个结论,假设唯一分解 (phi(x)=t_1^{k_1} cdot t_2^{k_2} cdots t_n^{k_n}) ,则只需要枚举 (frac{phi(x)}{t_i}) ,而非 (phi(x)) 的所有约数。
C. 多项式运算
注意 fill
函数的区间必须 (l le r) ,否则会 RE 。
6. 矩阵
- 卷积
- 矩阵乘法
- 行列式(性质、用高斯消元计算行列式)
- Vandermonde 矩阵的性质(计算行列式)
- Laplace expansion(计算行列式)
- 特征多项式
- 秩、子式、(代数)余子式
- 拉格朗日插值
行列式计算
性质:
- (det(A)=det(A^T))
- 交换两行,行列式变为相反数。
- 一行同乘 (k) ,行列式乘 (k) 。
- 只有一行不同的两个矩阵,行列式之和等于他们两行元素分别对应相加形成的矩阵的行列式。
- 行列和均为 (0) 的矩阵行列式为 (0) 。
7. 组合计数
A. 生成函数(母函数)
三种生成函数,对应了不同意义下的多项式加法和乘法。多项式乘法可以解决一些“拼接”相关的问题。
OGF
数列 (a_i) 的 OGF 是 (f(x)=sum_{i=0}^{infty} a_ix^i) ,用来处理无标号问题。
一个很常见的 OGF 是:
它的多项式加法意义略过,乘法意义是 (c_n=sum_{i+j=n} a_ib_j) 。
举个例子看下它的作用。
定义一个数列 (a) 第 (k) 项表示方程 (sum_{i=1}^k t_i = x (t_i in N)) 的解的数量。
数列每一项用插板法都可以直接计算,构造 (a) 的生成函数:
运用拼接的方法,可以得到:
也可以不断求导,增加指数来归纳出这个式子,但解题当然不会用那种方法。
如果需要构造复杂一些的 OGF ,可以用类似退项作差的方法。
EGF
数列 (a_i) 的 EGF 是 (f(x)=sum_{i=0}^{infty} a_i dfrac{x^i}{i!}) ,用来处理有标号问题。
它的多项式乘法意义自带了一个组合数 (c_n=sum_{i+j=n} (^n_i)a_ib_j) ,把卷积式子直接展开就长这样。
如果 (n) 个点带标号无向图的数量记为 (a_n=2^{(^n_2)}) ,它的 EGF 是 (f(x)) ,那么 (n) 个点带标号无向连通图的 EGF (g(x)=ln f(x)) 。
带标号树的 EGF (f(x)) 可以用 Prufer 序列算,森林设为 (g(x)) ,有 (g(x)=e^{f(x)}) 。
B. 容斥原理
有时可以构造容斥系数,再把常数换成一个函数(比如 (f(n) =epsilon(n))),然后用反演来得到容斥系数。
min-max 容斥
一种证明方法是考虑一个数 (x) 的系数,设比 (x) 大的数个数是 (k) ,则系数为 (sum_{i=0}^k (^k_i) imes (-1)^{i+1+1} = ((-1)+1)^k) ,当且仅当 (k=0) 时取 (1) ,所以只有最大的数有一个系数 (1) 。
这个东西有时候可以凭借意念推广到广义的情况,即 (min) 表示至少怎样, (max) 表示全部怎样的情况,为什么呢?我也不知道。
C. 二项式反演
D. 两类斯 Stirling 数
第一类(圆桌问题、环排列问题):
有一道题 Codeforces 960G ,答案是组合数乘上一个第一类 Stirling 数,数据范围很大。然后学习了到第一类 Stirling 数的一种快速求法。考虑组合意义( T_T 我知道这句话非常吸引火力)数列 ([^n_0],[^n_1],[^n_2],cdots) 的生成函数:
分成 ([l,mid)vee[mid,r)) ,FFT 求解(网上竟然有人把这叫做分治 FFT, 不对呀), (O(nlog^2 n)) 。
有时还是会被卡。在 组合计数和反演 - 小蒟蒻yyb 里发现了更好的方法:
设 (n=2m) ,则:
设 (g(m)=prod_{i=0}^{m-1}((x+m)+i)) ,则 (f(n)=f(m)cdot g(m)) 。
(f(m)=prod_{i=0}^{m-1}(x+i)) ,设这个 (m) 次多项式的各项系数为 (a) ,即 (f(m)=sum_{i=0}^{m}a_ix^i) ,那么有:
最后一步是在改换枚举顺序。设 (g) 的系数为 (b) ,观察上式得到:
先忽略和式外面,和式里面翻转两个中的任意一个后,是一个卷积形式。比如,设一个函数的系数是 (c_{m-i}=a_icdot i!) ,则下标和为 (m-j) 。
还是递归求解,但是每次可以根据左边的 (f) ,快速算右边的 (g) ,再乘起来得到当前答案, (O(nlog n)) 。
第二类(集合划分问题):
第二类斯特林数的容斥形式:
考虑容斥,枚举空盒至少有 (k) 个,把球往剩下的 (m-k) 个盒子里丢。
这是一个卷积形式,所以 ([^n_0],[^n_1],cdots,[^n_n]) 可以 (O(n log n)) 求。
套路
自然数幂和
左边是盒子和球都有序的方案数。右边枚举非空盒子数量,然后用斯特林数往里面扔球。
Stirling Inversion
处理集合划分,图的连通的时候可能会有用。
两种常见方法:
-
构造函数,一个表示恰好,一个表示 (ge) ,后者易求,然后反演。比如: (f(n)) 表示恰好 (n) 个连通块, (g(n)) 表示至少 (n) 个,要求 (f(1)) 。
-
构造容斥系数,考虑一个东西 (n) 在用 (ge) 的计算方法计算时,会被计算的次数,有时它和 (n) 的子集划分之类的东西有关。加入会被计算 (sum_{i}{^n_i}) 次,但希望只计算 (g(m)) 次,则构造 (sum_{i}{^n_i} f(i) = g(m)) ,然后反演一下,每次算出方案数,乘上容斥系数 (f) 再贡献给答案。
E. 数列的特征根
求:
设 (a_n = x^n) 满足 (x e 0) ,则 (x^n=sum_{k=1}^{m} x^{n-k} imes c_k) ,然后:
上面就是 (a) 数列的特征方程,解出来一些根 (x_i) ,存在:
所以带一些值进去就可以得到数列 (d) ,也就是得到了 (a) 的通项公式。
众所周知,矩乘优化递推是 (O(m^3nlog n)) 的。学习一下如何继续优化。