基础数论1
质数
试除法判定质数
bool judge(int n) {
for(int i = 2; i < n; i++) {
if(n % i == 0) return false;
}
return true;
}
时间复杂度: \(O(n)\)
优化
for(int i = 2; i <= n / i; i++) {
if(n % i == 0) return false;
}
return true;
}
时间复杂度 \(O(n) \Rightarrow O(\sqrt n)\)
试除法分解质因数
void work(int n) {
for(int i = 2; i <= n / i; i++) { //n中最多只包含一个大于等于sqrt(n)的质因子
if(n % i == 0) { //i一定为质数
int s = 0;
while(n % i == 0) {
n /= i;
s++;
}
}
cout << i << " " << s << endl; //i为底数,s为指数
}
if(n > 1) cout << n << " " << 1 << endl; //如果此时n大于1,那么它就是唯一一个大于sqrt(n)的质因子,单独处理
}
时间复杂度: \(O(\sqrt n)\)
筛法
原理:筛去倍数
朴素筛法
void work(void) {
for(int i = 2; i <= n; i++) {
if(!st[i]) {
primes[cnt++] = i;
}
for(int j = i + i; j <= n; j += i) st[j] = true;
}
}
时间复杂度:\(O(n \log n)\)
埃氏筛:只筛去质数的倍数
void work(void) {
for(int i = 2; i <= n; i++) {
if(!st[i]) {
primes[cnt++] = i;
for(int j = i + i; j <= n; j += i) st[j] = true;
}
}
}
时间复杂度:\(O(\log \log n)\)
质数定理:\(1 \sim n\) 中有 \(\frac{n}{\ln n}\) 个质数
线性筛:保证每个合数被最小的质因子筛去
void work(void) {
for(int i = 2; i <= n; i++) {
if(!st[i]) primes[cnt++] = i;
for(int j = 0; primes[j] <= n / i; j++) {
st[primes[j] * i] = true;
if(i % primes[j] == 0) break; //此时primes[j]一定是i的最小质因子
}
}
}
正确性证明:
- \(i \mod primes[j] = 0\)
\(primes[j]\) 是 \(i\) 的最小质因子,因此 \(primes[j]\) 一定是 \(primes[j] \times i\) 的最小质因子。 - \(i \mod primes[j] \neq 0\)
\(primes[j]\) 一定小于 \(i\) 的所有质因子,因此 \(primes[j]\) 一定是 \(primes[j] \times i\) 的最小质因子。
约数
试除法求约数
void work(void) {
vector<int> divisors;
for(int i = 2; i <= n / i; i++) {
if(n % i == 0) {
divisors.push_back(i);
if(i != n / i) divisors.push_back(n / i);
}
}
sort(divisors.begin(), divisors.end());
}
唯一分解定理
任何一个大于 \(1\) 的整数 \(N\) 一定可以分解成以下形式:
\[N = p_1^{\alpha_1}p_2^{\alpha_2}...p_k^{\alpha_k}
\]
其中 \(p_1, p_2, ... , p_k\) 为质数
求约数的个数
\[(\alpha_1 + 1)(\alpha_2 + 1)...(\alpha_k + 1)
\]
对于分解出来的每个约数,我们均可再次分解成\(p_1^{\beta_1}p_2^{\beta_2}...p_k^{\beta_k}\)的形式,其中 \(0 \leq \beta_i \leq \alpha_i\) 。选择不同的项可以组成不同的数,对于每个式子,有\(\alpha_i + 1\)中选择(还可以都不选,也就是1),因此约数的个数一共有$ (\alpha_1 + 1)(\alpha_2 + 1)...(\alpha_k + 1) $ 个。
求约数之和
\[(p_1^0 + p_1^1 + ... + p_1^{\alpha_1})...(p_k^0 + p_k^1 + ... + p_k^{\alpha_k})
\]
其实是将所有约数的分解式按分配律整理后的形式。
最大公约数
辗转相除法求最大公约数
\[\gcd(a, b) = \gcd(b, a \mod b)
\]
int gcd(int a, int b) {
return b ? gcd(b, a % b) : a;
}

浙公网安备 33010602011771号