性质:
整除符号
所以我们可以只枚举每对因数中较小的那一个,即满足
等价于
于是我们有
试除法
void getDivisors(int n) {
for (int i = 1; i <= n / i; i++) {
if (n % i) continue;
cout << i << ' ';
if (i != n / i) cout << n / i << ' ';
}
}
三种写法:
i<=sqrt(n) 浪费时间(不推荐),i*i<=n 可能爆 int,除法稍微慢一点
小知识:一个数的因数数量大概是多少?
试除法
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 divide(int n) {
for (int i = 2; i <= n / i; i++) {
if (n % i) continue;
// 此时i一定是质数,为什么?
int c = 0;
while (n % i == 0)
n /= i, c++;
cout << i << ' ' << c << '\n';
}
// 最多只有1个>sqrt(n)的质因子,为什么?
if (n > 1) cout << n << ' ' << 1;
}
唯一分解定理是解决因数问题的常用工具
因数个数:
解释:
代码实现:开个map
唯一分解定理是解决因数问题的常用工具
因数之和:
解释:展开有惊喜,可举例帮助理解
代码实现:每次
找出
朴素筛
埃氏筛
线性筛
为什么叫“筛”?
在
最后剩下的没被筛掉的数就是质数
bool notPri[N];
int primes[N], tot;
void getPrimes(int n) {
for (int i = 2; i <= n; i++) {
if (!notPri[i]) primes[++tot] = i;
for (int j = i + i; j <= n; j += i)
notPri[j] = true;
}
}
朴素筛法的复杂度是多少?
小知识:调和级数
朴素筛法的复杂度:
对朴素筛的改进:只删掉质数的倍数(因为合数一定能被它的质因子筛掉)
bool notPri[N];
int primes[N], tot;
void getPrimes(int n) {
for (int i = 2; i <= n; i++) {
if (!notPri[i]) { //只有这一点区别
primes[++tot] = i;
for (int j = i + i; j <= n; j += i)
notPri[j] = true;
}
}
}
埃氏筛的复杂度是多少?
质数分布小规律:
思考:本来要用
上面的估计很不准确。实际上应该是
埃式筛已经“几乎”是线性的,
还能更快:每个合数只被它的最小质因子筛一次,复杂度
// 巨常用,要理解+记忆
bool notPri[N];
int primes[N], tot;
void getPrimes(int n) {
for (int i = 2; i <= n; i++) {
if (!notPri[i]) primes[++tot] = i;
for (int j = 1; primes[j] <= n / i; j++) {
notPri[primes[j] * i] = true; //注意i和j不要写错
if (i % primes[j] == 0) break;
}
}
}
为什么每个合数只被它的最小质因子筛一次?
不难发现,primes[j] 要么比 i 的最小质因子还小(break之前),要么就是 i 的最小质因子(break时)
所以 primes[j] 一定是 primes[j] * i 的最小质因子!
另一种推荐写法:线性筛,顺便求每个数的最小质因子
这种写法可能更能体现欧拉筛的思想
int p[N], primes[N], tot;
void getPrimes(int n) {
p[1] = 1; // 根据题目需要设定p[1]的值
for (int i = 2; i <= n; i++) {
if (!p[i]) p[i] = i, primes[++tot] = i;
for (int j = 1; primes[j] <= n / i; j++) {
p[primes[j] * i] = primes[j];
if (p[i] == primes[j]) break;
}
}
}
对试除法分解质因数的改进:
先求出每个数的最小质因子(数组p[]),不必从 p[n] 来试除即可
复杂度: