目录
- 大纲
- 一.数学
- 1.唯一分解定理
- 例题:[GESP202309 五级] 因数分解
- 2.素数筛
- ·暴力筛
- ·埃氏筛
- ·欧拉筛
- 总结:
- 3.辗转相除法
- 1.唯一分解定理
大纲
一. 数学
二. 高精度
三. 单链表、双链表、循环链表
四. 二分查找/二分答案
五. 贪心算法
六. 分治算法(归并排序和快速排序)
七. 递归
八. 算法复杂度的估算(含多项式、指数、对数复杂度)
*粗体为常考内容
一.数学
- 唯一分解定理
- 素数表的埃氏筛法和线性筛法
- 辗转相除法(也称欧几里得算法)
1.唯一分解定理
定理:何一个大于1的整数n都可以分解成若干个素因数的连乘积,如果不计各个素因数的顺序,那么这种分解是惟一的,即若\(n>1\),则有\(n=p1*p2*…pm\)。质因数分解是实现唯一分解定理的具体方法,而定理则为该方法的有效性奠定了基础。如6被分为23,12被分为34或62再分为32*2,发现质因数分解的结果是唯一的。
例题:[GESP202309 五级] 因数分解
模板:
#include <bits/stdc++.h>
#define int long long
using namespace std;signed main() {int n;cin >> n;bool flag = false;for (int i = 2; i * i <= n; i++) {if (n % i == 0) {int cnt = 0;while (n % i == 0) {n /= i;cnt++;}if (cnt == 1)cout << i;elsecout << i << "^" << cnt;if (n > 1)cout << " * ";}}if (n > 1)cout << n;return 0;
}
2.素数筛
顾名思义,就是找出一定数字范围内的质数,普通的暴力方法就是枚举该数的所有因子,但有些情况速度过慢,于是就要用埃氏筛法和线性筛法等更快的筛法。
·暴力筛
bool is_prime(int n) {if (n < 2)return false;for (int i = 2; i * i <= n; i++) {if (!(n % i))return false;}return true;
}
·埃氏筛
从 2 开始,将每个质数的倍数标记为合数,直到遍历完所有数。未被标记的数即为质数。
void is_prime(int n) {vector <bool> prime(n + 1, true);for (int i = 2; i * i <= n; i++) {if (prime[i]) {for (int j = i * i; j <= n; j += i) {prime[j] = false;}}}for (int i = 2; i <= n; i++) {if (prime[i]) {cout << i << endl;}}return ;
}
·欧拉筛
欧拉筛是一种高效的质数筛选算法,也被称为线性筛法。其核心思想是 每个合数只被其最小质因数标记一次,从而避免了重复标记,提高了筛选效率。
void sieveOfEuler(int n) {vector<int> prime;vector<bool> isprime(n + 1, true);for (int i = 2; i <= n; i++) {if (isprime[i]) {prime.push_back(i);}for (int prj : prime ) { //遍历prime数组if (i * prj > n)break;isprime[prj * i] = false;if (i % prj == 0)break;}}for (int pri : prime) {cout << pri << endl;}return ;
}
总结:
方法 | 时间复杂度 | 优点 | 缺点 | 适用场景 |
---|---|---|---|---|
暴力筛法 | $ O(n \sqrt{n}) $ | 简单直观 | 效率低 | 小范围、学习用途 |
埃氏筛 | $ O(n \log \log n) $ | 高效、易于实现 | 重复标记、有一定冗余 | 中等范围 |
欧拉筛 | $ O(n) $ | 线性复杂度、无重复标记 | 实现复杂、需要额外空间 | 大规模 |
3.辗转相除法
设有\(a\),\(b(a>b)\) ,求a和b最大公约数。 令$a %\ b=r $ ,如果$ r=0 $,则b为a和b最大公约数,否则令 \(a=b\) ,\(b=r\) ,重复上述步骤。
int gcd(int a, int b) {if (b == 0) return a; // 基线条件:当 b 为 0 时,GCD 为 a return gcd(b, a % b); // 递归调用:GCD(a, b) = GCD(b, a % b)
}