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

 

  

 

  

 

posted @ 2013-11-27 23:34  朝拜明天19891101  阅读(314)  评论(0编辑  收藏  举报