voidget_primes(int n) { for (int i = 2; i <= n; i ++ ) { if (st[i]) continue; primes[cnt ++ ] = i; for (int j = i + i; j <= n; j += i) st[j] = true; } }
线性筛
只被筛一次,被最小质因数筛
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
int primes[N], cnt; bool st[N];
voidget_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; } } }
欧拉函数
欧拉函数,即 ,表示的是小于等于和互质的数的个数。 比如说 。 当是质数的时候,显然有。
1 2 3 4 5 6 7 8 9 10 11 12 13
intphi(int x) { int res = x; for (int i = 2; i <= x / i; i ++ ) if (x % i == 0) { res = res / i * (i - 1); while (x % i == 0) x /= i; } if (x > 1) res = res / x * (x - 1);
LL CRT(int k, LL* a, LL* r){ LL n = 1, ans = 0; for (int i = 1; i <= k; i++) n = n * r[i]; for (int i = 1; i <= k; i++) { LL m = n / r[i], b, y; exgcd(m, r[i], b, y); // b * m mod r[i] = 1 ans = (ans + a[i] * m * b % n) % n; } return (ans % n + n) % n; }
数论分块
数论分块,又叫整除分块,数论分块可以快速计算一些含有除法向下取整的和式(即形如 的和式)。当可以在内计算或已经预处理出 f 的前缀和时,数论分块就可以在 的时间内计算上述和式的值。
给出一个结论,给定一个整数,则对于,属于正整数且小于,有种取值
用数学语言表示就是 $$ \forall n \in \mathbb{N}{+}, \left|\left{ \lfloor \frac{n}{d} \rfloor \mid d \in \mathbb{N}{+},d\leq n \right}\right| \leq \lfloor 2\sqrt{n} \rfloor $$
这也表示对于 的结果可以分成值相同的一段段,从而完成快速求和,这就是数论分块
1 2 3 4 5 6
for(int l = 1; l <= n; l++) { int d = n / l, r = n / d; // 表示[l,r]这一段 n / x 都 == d l = r; }