素数筛法 [FINISHED]
素数筛法. 从每一个素数开始, 把它的倍数设置为非素数.这样从小到达枚举的时候, 不是非素数的就是素数.
#include <cmath>
#include <vector>
template <typename TYPE,
typename = std::enable_if_t<std::is_integral<TYPE>::value>>
class PrimeSieve {
public:
PrimeSieve(TYPE n) : n(n), is_prime_mask_((n + 63) / 64) {
if (n < 2) {
return;
}
TYPE sqrtn = std::sqrt(n);
for (TYPE i = 3; i <= sqrtn; ++i) {
if (isprime(i)) {
TYPE curr = i * i;
TYPE t = (n - curr) / i / 2;
for (TYPE k = 0; k <= t; ++k, curr += 2 * i) {
is_prime_mask_[curr >> 6] |= (1 << (curr / 2 % 32));
}
}
}
for (TYPE i = 2; i <= n; ++i) {
if (isprime(i)) {
primes_.emplace_back(i);
}
}
}
inline auto count() const { return primes_.size(); }
template <typename INDEX_TYPE,
typename = std::enable_if_t<std::is_integral<INDEX_TYPE>::value>>
inline TYPE nth(INDEX_TYPE idx) const {
return primes_.at(idx);
}
inline bool isprime(TYPE t) const {
if (t == 2) {
return true;
}
if (t % 2 == 0 || t < 2) {
return false;
}
return !(is_prime_mask_[t >> 6] & (1 << (t / 2 % 32)));
}
private:
TYPE n;
std::vector<TYPE> primes_;
std::vector<unsigned int> is_prime_mask_;
};