筛法
我们有时需要预处理一些质数。对每一个数都进行素性测试太慢了,筛法是更好的选择。
以下讨论时不再强调
Eratosthenes 筛法
考虑数
从
cpp
vector<bool> not_p;
vector<int> primes;
void Eratosthenes(int n) {
not_p.resize(n + 1);
for (int i = 2; i <= n; i++) {
if (!not_p[i]) {
primes.push_back(i);
for (int j = i; j < n / i; j++)
not_p[i * j] = true;
}
}
}
vector<bool> not_p;
vector<int> primes;
void Eratosthenes(int n) {
not_p.resize(n + 1);
for (int i = 2; i <= n; i++) {
if (!not_p[i]) {
primes.push_back(i);
for (int j = i; j < n / i; j++)
not_p[i * j] = true;
}
}
}
记
容易发现,若
以上操作不改变复杂度,都是
Euler 筛法
注意到,我们每一个合数都重复标记了几次,需要优化。
从小到大枚举
因此对于每个合数,一定且仅会因为最小因子筛掉。因此复杂度
cpp
vector<bool> not_p;
vector<int> primes;
void Euler(int n) {
not_p.resize(n + 1);
for (int i = 2; i <= n; i++) {
if (!not_p[i])
primes.push_back(i);
for (auto pj : primes) {
if (pj > n / i)
break;
not_p[i * pj] = true;
if (i % pj == 0)
break;
}
}
}
vector<bool> not_p;
vector<int> primes;
void Euler(int n) {
not_p.resize(n + 1);
for (int i = 2; i <= n; i++) {
if (!not_p[i])
primes.push_back(i);
for (auto pj : primes) {
if (pj > n / i)
break;
not_p[i * pj] = true;
if (i % pj == 0)
break;
}
}
}
Euler 筛预处理积性函数
用 Euler 筛预处理积性函数
筛法过程中中,我们可以得到一个数的最小质因子
假设数
当数
并且要求
cpp
vector<bool> not_p;
vector<int> primes, phi, mu;
void Euler(int n) {
not_p.resize(n + 1);
phi.resize(n + 1);
mu.resize(n + 1);
mu[1] = phi[1] = 1;
for (int i = 2; i <= n; i++) {
if (!not_p[i]) {
primes.push_back(i);
phi[i] = i - 1, mu[i] = -1;
}
for (auto pj : primes) {
if (pj > n / i)
break;
not_p[i * pj] = true;
if (i % pj == 0) {
phi[i * pj] = phi[i] * pj;
mu[i * pj] = 0;
break;
}
phi[i * pj] = phi[i] * (pj - 1);
mu[i * pj] = -mu[i];
}
}
}
vector<bool> not_p;
vector<int> primes, phi, mu;
void Euler(int n) {
not_p.resize(n + 1);
phi.resize(n + 1);
mu.resize(n + 1);
mu[1] = phi[1] = 1;
for (int i = 2; i <= n; i++) {
if (!not_p[i]) {
primes.push_back(i);
phi[i] = i - 1, mu[i] = -1;
}
for (auto pj : primes) {
if (pj > n / i)
break;
not_p[i * pj] = true;
if (i % pj == 0) {
phi[i * pj] = phi[i] * pj;
mu[i * pj] = 0;
break;
}
phi[i * pj] = phi[i] * (pj - 1);
mu[i * pj] = -mu[i];
}
}
}