质数
质数判定(试除法)
bool isPrime(int n){
if(n < 2) return false;
for (int i = 2; i <= n / i; i ++ ){
if(n % i == 0) return false;
}
return true;
}
筛选质数
void primes(int n){
memset*(v, 0, sizeof(v));
for(int i = 2; i <= n; i++){
if(v[i]) continue;
//i是质数
cout << i << endl;
for(int j = i; i <= n / i; j++) v[i * j] = 1;
}
}
线性筛法
原理:每个合数会被它的最小质因子筛去
int st[N], primes[N];
void get_primes(int n) // 线性筛质数
{
for (int i = 2; i <= n; i ++ )
{
//如果没被标记,当前数i是质数
if (!st[i]) primes[cnt ++ ] = i;
for (int j = 0; primes[j] <= n / i; j ++ )
{
//当前质数的i倍不是质数,筛选掉
st[primes[j] * i] = true;
if (i % primes[j] == 0) break;
}
}
}
质因数分解
N = p 1 c 1 p 2 c 2 . . . p m c m N = p_1^{c_1}p_2^{c_2}...p_m^{c_m} N=p1c1p2c2...pmcm
c i 都 是 正 整 数 , p i 都 是 质 数 , 且 p 1 < p 2 < . . . < p m c_i都是正整数,p_i都是质数,且 p1<p2<...<pm ci都是正整数,pi都是质数,且p1<p2<...<pm
- 分解质因数的代码
typedef pair<int, int> PII;
//时间复杂度根号n
vector<PII> divide(int n){
vector<PII> v;
for(int i = 2; i <= n / i; i++){
//一个合数的因子在扫描到这个荷属之前就从N中筛选掉了,所以能整除n的一定是质数
if(n % i == 0){
int cnt = 0;
while(n % i == 0){
cnt++;
n /= i;
}
//i的cnt次方
v.push_back({i, cnt});
}
}
//n如果没有被2到根号n整数,则n是质数
if(n > 1) v.push_back({n, 1});
return v;
}
约数
N = p 1 c 1 p 2 c 2 . . . p m c m N = p_1^{c_1}p_2^{c_2}...p_m^{c_m} N=p1c1p2c2...pmcm
正约数个数
n = ( c 1 + 1 ) ∗ ( c 2 + 1 ) ∗ . . . ∗ ( c m + 1 ) n = (c_1+ 1)*(c_2 + 1)*...*(c_m+1) n=(c1+1)∗(c2+1)∗...∗(cm+1)
正约数之和
s = ( p 1 0 + p 1 1 + p 1 2 + . . . + p 1 c 1 ) ∗ . . . ∗ ( p m 0 + p m 1 + p m 2 + . . . + p m c m ) s=(p_1^0+p_1^1+p_1^2+...+p_1^{c1})*...*(p_m^0+p_m^1+p_m^2+...+p_m^{c_m}) s=(p10+p11+p12+...+p1c1)∗...∗(pm0+pm1+pm2+...+pmcm)
试除法
作用: 求一个数的约数集合
时间复杂度:
O
(
n
)
O(\sqrt n)
O(n)
核心思想:若d能整除n,则n/d也能整除n
vector<int> approximateNumber(int n){
vector<int> v;
//(i*i <= n) => (i <= n / i)
for (int i = 1; i <= n / i; i ++ ){
if(n % i == 0){
v.push_back(i);
if(n / i != i)v.push_back(n / i);
}
}
return v;
}
倍数法
作用:求1~n每个数的正约数集合
时间复杂度:
O
(
n
l
o
g
n
)
O(nlog{n})
O(nlogn)
核心思想:对于每个约数d,以d为约数的数是d的倍数,如
d
,
2
d
,
.
.
.
[
n
/
d
]
∗
d
d,2d,...[n/d]*d
d,2d,...[n/d]∗d
const int N = 1e5 + 10;
vector<vector<int>> multiple(int n){
vector<vector<int>> r(N);
//遍历每个约数d
for (int i = 1; i <= n; i ++ ){
//以d为约数的数是d的倍数
for (int j = 1; j <= n / i; j ++ ){
r[i * j].push_back(i);
}
}
return r;
}
最大公约数
更相减损术
若
a
>
=
b
a>=b
a>=b,有
g
c
d
(
a
,
b
)
=
g
c
d
(
b
,
a
−
b
)
=
g
c
d
(
a
,
a
−
b
)
gcd(a,b)=gcd(b,a-b)=gcd(a,a-b)
gcd(a,b)=gcd(b,a−b)=gcd(a,a−b)
对于所有a, b属于正整数
g
c
d
(
2
a
,
2
b
)
=
2
g
c
d
(
a
,
b
)
gcd(2a,2b) = 2gcd(a,b)
gcd(2a,2b)=2gcd(a,b)
int gcd(int a, int b){
if(b <= 0) return a;
if(a < b) swap(a, b);
return gcd(b, a - b);
}
欧几里得算法
对于所有a,b属于正整数,且b不等于0,有 g c d ( a , b ) = g c d ( b , a m o d b ) gcd (a,b)=gcd(b,a\ {mod}\ b) gcd(a,b)=gcd(b,a mod b)
int gcd(int a, int b) // 欧几里得算法
{
return b > 0 ? gcd(b, a % b) : a;
}
互质与欧拉函数
N = p 1 c 1 p 2 c 2 . . . p m c m N = p_1^{c_1}p_2^{c_2}...p_m^{c_m} N=p1c1p2c2...pmcm
欧拉函数
定义:1~N中与N互质的数的个数被称为欧拉函数,记为
φ
(
N
)
\varphi(N)
φ(N)
φ
(
N
)
=
N
∗
p
1
−
1
p
1
∗
p
2
−
1
p
2
∗
.
.
.
∗
p
m
−
1
p
m
\varphi(N) = N * {\frac{p_1-1}{p_1}}* {\frac{p_2-1}{p_2}}*...* {\frac{p_m-1}{p_m}}
φ(N)=N∗p1p1−1∗p2p2−1∗...∗pmpm−1
欧拉函数的实现
//分解质因数的模板
int phi(int n){
int ans = n;
for (int i = 2; i <= n / i; i ++ ){
if(n % i == 0){
//先除再乘,防止溢出
ans = ans / i * (i - 1) ;
while(n % i == 0) n /= i;
}
}
if(n > 1) ans = ans / n * (n - 1);
return ans;
}
同余
同余类与剩余系
同余类是一个集合,这个集合的每个数模m都等于同一个数a
在一个数m中,有模m为0的数构成的集合 0 ‾ \overline 0 0,有模m为1的数构成的集合 1 ‾ \overline 1 1,…,有模m为m-1的数构成的集合 m − 1 ‾ \overline {m-1} m−1
根据欧拉函数知道1~m中与m互质的数有 φ ( m ) \varphi(m) φ(m)个,如与10互质的质数有{1,3,7,9}, 有模m为1的数构成的集合 1 ‾ \overline 1 1,有模m为3的数构成的集合 3 ‾ \overline 3 3,有模m为5的数构成的集合 5 ‾ \overline 5 5,有模m为9的数构成的集合 9 ‾ \overline 9 9;所以10的简化剩余系是{ 1 ‾ \overline 1 1, 3 ‾ \overline 3 3, 5 ‾ \overline 5 5, 7 ‾ \overline 7 7}
费马小定理
a p m o d p = a m o d p a^p\ mod \ p = a\ mod \ p ap mod p=a mod p(p为质数,a为任意整数)
欧拉定理
欧拉定理的推论
扩展欧几里得算法
Bézout定理(裴蜀定理)
算法代码
int exgcd(int a, int b, int &x, int &y){
if(b == 0){
//递归边界,一定有b=0
//a * 1 + 0 * 0 = gcd(a, 0)
x = 1; y = 0;
return a;
}
//b > 0
int d = exgcd(b, a % b, y, x);
y -= (a / b) * x;
return d;
}
乘法逆元
b
∣
a
,
b
整
除
a
,
b
为
被
除
数
,
a
为
除
数
,
a
%
b
=
0
b | a,b整除a,b为被除数,a为除数,a \% b = 0
b∣a,b整除a,b为被除数,a为除数,a%b=0
当
模
数
为
质
数
时
,
b
p
−
2
即
为
b
的
乘
法
逆
元
当模数为质数时,b^{p-2}即为b的乘法逆元
当模数为质数时,bp−2即为b的乘法逆元
线性同余方程
a
∗
x
≡
b
(
m
o
d
m
)
=
>
a
∗
x
−
b
是
m
的
倍
数
,
不
妨
设
为
−
y
倍
。
于
是
,
该
方
程
可
以
改
写
为
a
∗
x
+
m
∗
y
=
b
a*x\equiv b(mod\ m) => a * x -b 是m的倍数,不妨设为-y倍。于是,该方程可以改写为a*x+m*y=b
a∗x≡b(mod m)=>a∗x−b是m的倍数,不妨设为−y倍。于是,该方程可以改写为a∗x+m∗y=b
线
性
同
余
方
程
有
解
当
且
仅
当
g
c
d
(
a
,
m
)
∣
b
线性同余方程有解当且仅当gcd(a,m)\ |\ b
线性同余方程有解当且仅当gcd(a,m) ∣ b
在
有
解
时
,
先
用
欧
几
里
得
算
法
求
出
一
组
整
数
x
0
,
y
0
,
满
足
a
∗
x
0
+
m
∗
y
0
=
g
c
d
(
a
,
m
)
。
然
后
x
=
x
0
∗
b
/
g
c
d
(
a
,
m
)
就
是
源
线
性
同
余
方
程
的
一
个
解
。
在有解时,先用欧几里得算法求出一组整数x_0,y_0,满足a*x_0+m*y_0=gcd(a,m)。然后x=x_0*b/gcd(a,m)就是源线性同余方程的一个解。
在有解时,先用欧几里得算法求出一组整数x0,y0,满足a∗x0+m∗y0=gcd(a,m)。然后x=x0∗b/gcd(a,m)就是源线性同余方程的一个解。
方
程
的
通
解
是
所
有
模
m
/
g
c
d
(
a
,
m
)
与
x
同
余
的
整
数
方程的通解是所有模m/gcd(a, m)与x同余的整数
方程的通解是所有模m/gcd(a,m)与x同余的整数
中国剩余定理
矩阵乘法
一个nm的矩阵可看作为一个nm的二维数组。矩阵加法和减法就是把两个矩阵对应位置上的数相加减
第一个矩阵的列数必须等于第二个矩阵的行数,所以结果的行数、列数分别等于第一个矩阵的行数、第二个矩阵的列数。矩阵C第第i行第j列的数,是由A的第i行的m个数与B的第j列的m个数分别相乘再相加得到的。
高斯消元与线性空间
高斯消元
高斯消元是一种求解线性方程组的方法。
线性方程组是M个N元一次方程共同构成的;系数矩阵 + 行方程等号的常数 = 增广矩阵,例如
线性空间
给定若干个向量
a
1
.
a
2
,
.
.
.
,
a
k
a_1.a_2,...,a_k
a1.a2,...,ak,若向量b能有
a
1
,
a
2
.
.
.
,
a
k
a_1,a_2...,a_k
a1,a2...,ak经过向量加法和标量乘法运算得出,则称向量b能被向量
a
1
,
a
2
,
a
k
a_1,a_2,a_k
a1,a2,ak表出
.显然,
a
1
,
a
2
,
a
k
a_1,a_2,a_k
a1,a2,ak能表出的所有向量构成一个线性空间,
a
1
,
a
2
,
a
k
a_1,a_2,a_k
a1,a2,ak被成为这个线性空间的生成子集。
任意选出线性空间中的若干个向量,若干其中存在一个向量能被其他向量表出,则称这些向量线性相关,否则称这些向量线性无关。
线性无关的生成自己被称为线性空间的基底,简称基。基的另一种定义是线性空间的极大线性无关子集。一个线性空间的所有基包含的向量个数都相等,这个数被成为线性空间的维数。
例如二维坐标系的一个基底是{(1,0), (0, 1)}, 因为(1,0)和(0,1)不能被其他向量表出;一维x轴上的所有向量构成一维线性空间,它的一个基底是{(1,0)}
组合计数
加法原理
若完成一件事的方法有n类,第i类方法包括 a i a_i ai种不同的方法,且这些方法不重合,则完成这件事一共有 a 1 + a 2 + , , , + a n a_1+a_2+,,,+a_n a1+a2+,,,+an种不同的方法
乘法原理
若完成一件事需要n个步骤,第i个步骤有 a i a_i ai种不同的完成方法,且这些步骤互不干扰,则完成这件事有 a 1 ∗ a 2 ∗ . . . a n a_1*a_2*...a_n a1∗a2∗...an种不同的方法
排列数
从n个不同元素中依次取出m个元素排成一列,产生不同排列的数量为
A
n
m
=
n
!
(
n
−
m
)
!
=
n
∗
(
n
−
1
)
∗
.
.
.
∗
(
n
−
m
+
1
)
A^{m}_{n} = \frac{n!}{(n-m)!}=n*(n-1)*...*(n-m+1)
Anm=(n−m)!n!=n∗(n−1)∗...∗(n−m+1)
组合数
从n个不同元素取出m个组成一个集合(不考虑顺序),产生的不同集合数量为
C
n
m
=
n
!
m
!
(
n
−
m
)
!
=
n
∗
(
n
−
1
)
∗
.
.
.
∗
(
n
−
m
+
1
)
m
∗
(
m
−
1
)
∗
.
.
.
∗
2
∗
1
C^{m}_{n}=\frac{n!}{m!(n-m)!}=\frac{n*(n-1)*...*(n-m+1)}{m*(m-1)*...*2*1}
Cnm=m!(n−m)!n!=m∗(m−1)∗...∗2∗1n∗(n−1)∗...∗(n−m+1)
性质
- C n m = C n n − m C^m_n=C_n^{n-m} Cnm=Cnn−m
- C n m = C n − 1 m + C n − 1 m − 1 C^m_n=C_{n-1}^m+C_{n-1}^{m-1} Cnm=Cn−1m+Cn−1m−1
- C n 0 + C n 1 + . . . + C n n = 2 n C_n^0+C_n^1+...+C_n^n=2^n Cn0+Cn1+...+Cnn=2n
组合数的求法
根据性质2,用递推法求出结果,时间复杂度
O
(
n
2
)
O(n^2)
O(n2)。
若题目要求对数p取模,并且1~n都存在模p乘法逆元,则可以先计算分子
n
!
m
o
d
p
n! \ mod \ p
n! mod p,在计算分母
m
!
(
n
−
m
)
!
m
o
d
p
m!(n-m)! \ mod \ p
m!(n−m)! mod p的逆元,撑起来得到
C
n
m
m
o
d
p
,
复
杂
度
为
O
(
n
)
C^m_n\ mod \ p,复杂度为O(n)
Cnm mod p,复杂度为O(n)
二项式定理
( a + b ) n = ∑ k = 0 n C n k a k b n − k (a+b)^n=\sum_{k=0}^{n}C^k_na^kb^{n-k} (a+b)n=∑k=0nCnkakbn−k
多重集的排列数
多重集是包含重复元素的广义集合。设 S = { n 1 ∗ a 1 , n 2 ∗ a 2 , . . . , n k ∗ a k } 是 由 n 1 个 a 1 , n 2 个 a 2 . . . n k 个 a k 组 成 的 多 重 集 。 S 的 全 排 列 个 数 为 : S=\{n_1*a_1, n_2*a_2,...,n_k*a_k\}是由n_1个a_1,n_2个a_2...n_k个a_k组成的多重集。S的全排列个数为: S={n1∗a1,n2∗a2,...,nk∗ak}是由n1个a1,n2个a2...nk个ak组成的多重集。S的全排列个数为:
n ! n 1 ! n 2 ! , , , n k ! \frac{n!}{n_1!n_2!,,,n_k!} n1!n2!,,,nk!n!
多重集的组合数
设 S = { n 1 ∗ a 1 , n 2 ∗ a 2 , . . . , n k ∗ a k } 是 由 n 1 个 a 1 , n 2 个 a 2 . . . n k 个 a k 组 成 的 多 重 集 S=\{n_1*a_1, n_2*a_2,...,n_k*a_k\}是由n_1个a_1,n_2个a_2...n_k个a_k组成的多重集 S={n1∗a1,n2∗a2,...,nk∗ak}是由n1个a1,n2个a2...nk个ak组成的多重集,从S中取出r个元素组成一个多重集(不考虑元素顺序),产生的不同多重集的数量为:
C k + r − 1 k − 1 C^{k-1}_{k+r-1} Ck+r−1k−1
Lucas定理
(catalan)卡特兰数
容斥原理和Möbius函数
容斥原理
简单来说就是减去加多的部分,加上减多的部分
大写字母代表集合
A
∪
B
=
A
+
B
−
A
∩
B
A\cup B = A + B - A \cap B
A∪B=A+B−A∩B
A
∪
B
∪
C
=
A
+
B
+
C
−
(
A
∩
B
+
A
∩
C
+
B
∪
C
)
+
A
∩
B
∩
C
A \cup B \cup C = A + B + C -(A \cap B+A \cap C + B\cup C)+A\cap B \cap C
A∪B∪C=A+B+C−(A∩B+A∩C+B∪C)+A∩B∩C
(Möbius)莫比乌斯函数
N
包
含
相
等
的
质
因
子
时
μ
(
N
)
=
0
;
当
N
有
偶
数
个
不
同
的
质
因
子
时
μ
(
N
)
=
1
;
当
N
有
奇
数
个
不
同
的
质
因
子
时
μ
(
N
)
=
−
1
N包含相等的质因子时\mu(N) = 0;当N有偶数个不同的质因子时\mu(N)=1;当N有奇数个不同的质因子时\mu(N)=-1
N包含相等的质因子时μ(N)=0;当N有偶数个不同的质因子时μ(N)=1;当N有奇数个不同的质因子时μ(N)=−1
求 μ ( N ) \mu(N) μ(N),分解质因数模板即可
int mu1(int n){
int z = 0;
for (int i = 2; i <= n / i; i ++ ){
if(n % i == 0){
z++;
n /= i;
if(n % i == 0) return 0;
}
}
if(n > 1) z++;
if(z % 2 == 1) return -1;
else if(z % 2 == 0) return 1;
}
求
1
N
的
每
一
个
数
的
莫
比
乌
斯
值
,
可
以
用
埃
氏
筛
选
法
求1~N的每一个数的莫比乌斯值,可以用埃氏筛选法
求1 N的每一个数的莫比乌斯值,可以用埃氏筛选法
把所有
μ
\mu
μ值初始化为1,对于每个质数p,零
μ
(
p
)
=
−
1
,
并
扫
描
p
的
倍
数
x
=
2
p
,
3
p
,
.
.
.
,
检
查
x
能
否
被
p
2
整
除
。
若
能
μ
(
x
)
=
0
,
否
则
μ
(
x
)
=
−
μ
(
x
)
\mu(p)=-1,并扫描p的倍数x=2p,3p,...,检查x能否被p^2整除。若能\mu(x)=0,否则\mu(x)=-\mu(x)
μ(p)=−1,并扫描p的倍数x=2p,3p,...,检查x能否被p2整除。若能μ(x)=0,否则μ(x)=−μ(x)
int mu3(int n){
for (int i = 1; i <= n; i ++ ) miu[i] = 1, v[i] = 0;
for (int i = 2; i <= n; i ++ ){
if(v[i] == 1) continue;
miu[i] = -1;
for (int j = 2 * i; j <= n; j += i){
v[j] = 1;
if((j / i) % i == 0) miu[j] = 0;
else miu[j] *= -1;
}
}
}
概率与数学期望
样本点:一个随机试验的某种可能称为样本点
样本空间:所有可能构成的集合
随机事件:样本空间的子集
随机变量:把样本点映射为实数的函数
数学期望:随机变量取值与概率的乘积之和,E(X) =
∑
p
i
x
i
\sum p_ix_i
∑pixi,
x
i
xi
xi是随机变量的取值,
p
i
p_i
pi是对应的概率
数学期望是线性函数。满足 E ( a X + b Y ) = a ∗ E ( X ) + b ∗ E ( Y ) E(aX+bY)=a*E(X)+b*E(Y) E(aX+bY)=a∗E(X)+b∗E(Y)
博弈论之SG函数
NIM博弈
给定 n n n堆物品,第 i i i堆物品有 A i A_i Ai个。两名玩家轮流行动,每次可以任选一堆,取走任意多个物品,可把一堆取光,但不能不取。取走最后一件物品者获胜。两人都采取最优策略,问先手能否必胜,
公平组合游戏ICG
若一个游戏满足
1.由两名玩家交替行动
2.在游戏进程的任意时刻,可以执行的合法行动与轮到哪名玩家无关
3.不能行动的玩家判负
则称该游戏为一个公平组合游戏
有向图游戏
给定一个有向无环图,图中有一个唯一的起点,在起点上放有一枚棋子。两名玩家交替地把这枚棋子沿有向边进行移动,每次可以移到一步,无法移到者判负。该游戏被称为有向图游戏。
任何一个公平组合游戏都可以转化为有向图游戏。具体方法是,把每个局面看成图中的一个节点,并 且从每个局面沿着合法行动能够达到的下一局面连有向边
Mex运算
设
S
S
S表示一个非负整数集合。定义
m
e
x
(
S
)
mex(S)
mex(S)为求出不属于集合
S
S
S的最小非负整数的运算,即
m
e
x
(
S
)
=
m
i
n
x
∈
N
,
x
∉
S
{
x
}
mex(S)=min_{x\in N,x \notin S}\{x\}
mex(S)=minx∈N,x∈/S{x}
SG函数
在有向图游戏中,对于每个起点
x
x
x,设从
x
x
x出发共有
k
k
k条有向边,分别到达节点
y
1
,
y
2
,
.
.
.
,
y
k
y_1,y_2,...,y_k
y1,y2,...,yk,定义
S
G
(
x
)
SG(x)
SG(x)为
x
x
x的后继节点
y
1
,
y
2
,
.
.
,
y
k
y_1,y_2,..,y_k
y1,y2,..,yk的
S
G
SG
SG函数值构成的集合再执行
m
e
x
mex
mex运算的结果,即:
S
G
(
x
)
=
m
e
x
(
{
S
G
(
y
1
)
,
S
G
(
y
2
)
,
.
.
.
,
S
G
(
y
k
)
}
)
SG(x)=mex(\{SG(y_1),SG(y_2),...,SG(y_k)\})
SG(x)=mex({SG(y1),SG(y2),...,SG(yk)})
定理
有向图游戏的某个局面必败,当且仅当当局面对应节点的
S
G
SG
SG函数值大于0。
有向图游戏的某个局面必败,当且仅当该局面对应节点的
S
G
SG
SG函数值等于0。