欧拉筛:
const int N= 1000010;
int primes[N], cnt;
bool st[N];
oid get_prime(int x) {
for(int i = 2; i <= x; i++) {
if(!st[i]) prime[cnt++] = i;
for(int j = 0; prime[j] <= x / i; j++) {
st[prime[j]*i] = true;
if(i % prime[j] == 0) break;
}
}
}
欧拉筛的证明:
i%primes[j]==0
1.primes[j]是i的最小质因子
2.如果标记i*primes[j+1]......i*primes[j] 对应的最小质因子是primes[j]<primes[j+1],违反了只标记最小质因子为primes[j]的原则
3. i*primes[j+1]应该留给 i_new=i*primes[j+1]/primes[j]去标记
i%primes[j]!=0
1:如果i是合数,那么i的最小质因子大于primes[j],i*primes[j]的最小质因子是primes[j]
2:如果i是质数,那么iprimes[j]的最小质因子就是primes[j]
3 综上i%primes[j]!=0 时,i*primes[j]的最小质因子就是primes[j]
1.综上:
1.这个代码只标记以primes[j]为最小质因子的合数n,由于一个合数n只有一个最小质因子,所以一个合数最多被标记一次
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
2.1一个合数n有且仅有一个最小质因子k1,n/k1>=k1,所以primes数组一定包含k1(因为primes数组包含小于n/k1的所有素数).
2.2对于i=n/k,primes包含k1.如果i=n/k是素数那么在primes[k0]<primes[k1]之前一定不会退出循环直到n/k%k=0,如果i=n/k是合数那么在primes[k0]<primes[k1]之前k0不是n/k1的因子(因子n/k1的最小质因子>=k1因为n的最小质因子为k1),所以n/k1%primes[k0]!=0
2.综上:
2.3综上一个合数肯定在i=n/k1(k1为最小质因子)被标记
3.综综上:
3.由于一个合数最多被标记一次(1证),又由于一个合数一定被标记一次,所以一个合数能切仅能被标记一次时间复杂度O(n)