0
点赞
收藏
分享

微信扫一扫

算法数论.

年迈的代码机器 2022-02-03 阅读 38

质数

质数判定(试除法)

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,ab)=gcd(a,ab)
对于所有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)=Np1p11p2p21...pmpm1

欧拉函数的实现

//分解质因数的模板
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} m1

根据欧拉函数知道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 ba,babaa%b=0
当 模 数 为 质 数 时 , b p − 2 即 为 b 的 乘 法 逆 元 当模数为质数时,b^{p-2}即为b的乘法逆元 bp2b

线性同余方程

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 axb(mod m)=>axbmyax+my=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,y0ax0+my0=gcd(a,m)x=x0b/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 a1a2...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=(nm)!n!=n(n1)...(nm+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!(nm)!n!=m(m1)...21n(n1)...(nm+1)

性质

  1. C n m = C n n − m C^m_n=C_n^{n-m} Cnm=Cnnm
  2. 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=Cn1m+Cn1m1
  3. 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!(nm)! mod p的逆元,撑起来得到 C n m   m o d   p , 复 杂 度 为 O ( n ) C^m_n\ mod \ p,复杂度为O(n) Cnm mod pO(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=0nCnkakbnk

多重集的排列数

多重集是包含重复元素的广义集合。设 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={n1a1,n2a2,...,nkak}n1a1,n2a2...nkakS

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={n1a1,n2a2,...,nkak}n1a1,n2a2...nkak,从S中取出r个元素组成一个多重集(不考虑元素顺序),产生的不同多重集的数量为:

C k + r − 1 k − 1 C^{k-1}_{k+r-1} Ck+r1k1

Lucas定理

(catalan)卡特兰数

在这里插入图片描述

容斥原理和Möbius函数

容斥原理

在这里插入图片描述

简单来说就是减去加多的部分,加上减多的部分
大写字母代表集合
A ∪ B = A + B − A ∩ B A\cup B = A + B - A \cap B AB=A+BAB
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 ABC=A+B+C(AB+AC+BC)+ABC

(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)=1px=2p,3p,...,xp2μ(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)=aE(X)+bE(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)=minxN,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。

举报

相关推荐

0 条评论