素数筛法 [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_; };