1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
| #ifndef EULER_SEIVE_HPP #define EULER_SEIVE_HPP 1
#include <vector> #include <type_traits> #include <cmath>
namespace euler_seive { namespace type_traits__ { struct tag_base__ {}; struct null_tag: tag_base__ {}; struct min_pfactor_tag: tag_base__ {}; struct euler_phi_tag: tag_base__ {}; struct mobius_tag: tag_base__ {}; } using namespace type_traits__;
namespace detail__ { template <class Tp, bool IsNull, class Fp, class Fij, class Mulf> requires std::integral<Tp> constexpr auto seive_impl_(Tp n, Fp f_p, Fij f_ij, Mulf mulf) -> std::pair<std::vector<Tp>, std::vector<Tp>> { std::vector<Tp> ret, prime; std::vector<bool> vis((size_t)n);
if constexpr (!IsNull) { ret.resize((size_t)n); ret[1] = 1; } prime.reserve(n <= 55 ? 16 : n / (log((long double)n) - 4));
for (Tp i = 2; i < n; ++i) { if (!vis[i]) { vis[i] = 1; if constexpr (!IsNull) ret[i] = f_p(i); prime.push_back(i); } for (auto &&j : prime) { Tp ij = i * j; if (ij >= n) break; vis[ij] = 1; if (i % j == 0) { if constexpr (!IsNull) ret[ij] = f_ij(ret, i, j); break; } else if constexpr (!IsNull) ret[ij] = mulf(ret, i, j); } } return {prime, ret}; }
#define PARAMS_(v, i, j) (std::vector<Tp> const &v, Tp i, Tp j)
template <class Tp> constexpr auto seive_helper(Tp n, null_tag) { return seive_impl_<Tp, true>(n, nullptr, nullptr, nullptr); } template <class Tp> auto seive_helper(Tp n, min_pfactor_tag) { return seive_impl_<Tp, false>( n, [](Tp x) { return x; }, [] PARAMS_(v, i, j) { return j; }, [] PARAMS_(v, i, j) { return j; }); } template <class Tp> constexpr auto seive_helper(Tp n, euler_phi_tag) { return seive_impl_<Tp, false>( n, [](Tp x) { return x - 1; }, [] PARAMS_(v, i, j) { return v[i] * j; }, [] PARAMS_(v, i, j) { return v[i] * v[j]; }); } template <class Tp> constexpr auto seive_helper(Tp n, mobius_tag) { return seive_impl_<Tp, false>( n, [](Tp x) { return -1; }, [] PARAMS_(v, i, j) { return 0; }, [] PARAMS_(v, i, j) { return v[i] * v[j]; }); }
#undef PARAMS_ }
template <class Tp, class Tag> requires std::derived_from<Tag, tag_base__> constexpr auto seive(Tp n) { return detail__::seive_helper<Tp>(n, Tag{}); } }
#endif
|