数论

前置知识:

a|b(“|”是整除符号),读作“a整除b”或“b能被a整除”。a叫做b的约数(或因数),b叫做a的倍数。

质数 是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。

(1)判定——试除法

遍历查找,能否找到一个值为2~n-1的i,且i|n, 即i整除n;

bool is_prime(int n) {
	if (n < 2) return false;
	for (int i = 2; i < n; i++)
		if (n % i == 0) return false;
	return true;
}

试除法优化

假设d能整除n,则有(n / d)能整除n,而我们只需要找到一个

for (int i = 2; i <= n / i; i++)

i * i <= n 可能会出现溢出(i+1)*(i+n) > int_max的情况,溢出为负值会影响判断。

时间复杂度O(sqrt(n))

(2)分解质因数——试除法

  1. 暴力做法

i为什么一定是质数?因为当循环经历过i=2之后则i的倍数均不可能满足

void divide(int n) {
    for (int i = 2; i <= n; i++) {
        if (n % i == 0) { // i 一定是质数
            int sum = 0;
            while (n % i == 0) {
                n /= i;
                sum++;
            }
            printf("%d %d
", i, sum);
        }
    }
}

时间复杂度优化

void divide(int n) {
    for (int i = 2; i <= n / i; i++) {
        if (n % i == 0) { // i 一定是质数
            int sum = 0;
            while (n % i == 0) {
                n /= i;
                sum++;
            }
            printf("%d %d
", i, sum);
        }
    }
    if (n > 1) printf("%d %d
", n, 1);
    puts("");
}

时间复杂度O(sqrt(n))

(3)筛质数

算数基本定理

算术基本定理可表述为:任何一个大于1的自然数 N,如果N不为质数,那么N可以唯一分解成有限个质数的乘积

事件复杂度O(nlogn) 1~n中有(n/log{n}) 个质数

int primes[N], cnt;
bool st[N];

void get_primes(int n) {
    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;
    }
}

优化后,埃氏筛法

int primes[N], cnt;
bool st[N];

void get_primes(int n) {
    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;
        }
    }
}

线性筛法

核心:n只会被它的最小质因子筛掉

void get_primes(int n) {
    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的最小质因子
        }
    }
}

对于任意一个合数x,在x/pj时就会被筛掉

2. 约数

(1)试除法求一个数的所有约数

(2)约数个数

int范围内,约数最多为1500个

(3)约数之和

例题:约数个数

约数之和

(4)欧几里得算法(辗转相除法

核心公式:

代码:


3. 欧拉函数

欧拉函数定义:1~n中互质的数的个数

image-20200920234303419

则有如下公式:

image-20200920234508486

可以利用容氏原理来证明

原文地址:https://www.cnblogs.com/mayapony/p/13996407.html