(一)线性筛法
欧拉线性筛的流程是 对于每一个数, 扫一遍比它小的所有质数, 把这个数和这个质数的积标记为合数, 当这个数是这个质数的倍数的时候就break掉。
它实际上想要实现的只有一句话: 让每一个合数都被且只被它最小的质因子筛掉。 容易证明这样做以后的时间复杂度是O(n)的。
为什么这样做就可以实现这句话了呢?
证明:
设p 为一个合数(A)的最小的质因数, p'为这个合数的另一个质因数,
k = A / p; k' = A / p'
易证 k' 是p的倍数。
p 可以筛掉这个 合数, 但是p' 筛不掉。
考虑循环到k' 时, 这时j循环到p的时候就会被break掉了, 所以就走不到p' 所以A 没有被p'筛掉。
或者更直观地理解, 我们之所以要在 i 是 j 的倍数的时候break掉, 是因为这是如果不break 掉, 就会有 i * p (p 是比i 大的一个质数)被p在这是后筛掉, 但是事实上这个数是可以被j 这个更小的质因子筛掉的, 所以要在 i 这里break。
写起来也是简洁优美。
for(int i = 2; i <= N; i ++){
if(!flag[i])prim[++ pp] = i;
for(int j = 1; j <= pp && prim[j] * i <= N; j ++){
flag[i * prim[j]] = 1;
if(! i % prim[j])break;
}
}
(二)积性函数
积性函数是一种函数, 如果两个 自变量是互质的, 那么它们函数值的乘积 等于 它们乘积的函数值。即
考虑一个定义域为ℕ+的函数f,对于任意两个互质的正整数a,b,均满足 f(ab)=f(a) f(b)则函数f被称为积性函数。
----------- 一个很显然的性质是 f(N) = f(∏ pi ^ ai) = ∏ f(pi ^ ai).
----------- f(1) = 1
1, 欧拉函数