結果
問題 | No.3101 Range Eratosthenes Query |
ユーザー |
![]() |
提出日時 | 2025-04-12 18:52:32 |
言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 322 ms / 3,000 ms |
コード長 | 6,916 bytes |
コンパイル時間 | 1,436 ms |
コンパイル使用メモリ | 125,680 KB |
実行使用メモリ | 74,484 KB |
最終ジャッジ日時 | 2025-04-12 18:52:44 |
合計ジャッジ時間 | 9,106 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge3 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 2 |
other | AC * 24 |
ソースコード
#include <iostream> #include <iomanip> #include <cassert> #include <vector> #include <algorithm> #include <utility> #include <numeric> // #include "Src/Utility/BinarySearch.hpp" // #include "Src/Sequence/CompressedSequence.hpp" // #include "Src/Sequence/RunLengthEncoding.hpp" namespace zawa { template <class T> class AdditiveGroup { public: using Element = T; static constexpr T identity() noexcept { return T{}; } static constexpr T operation(const T& l, const T& r) noexcept { return l + r; } static constexpr T inverse(const T& v) noexcept { return -v; } }; } // namespace zawa #include <cstdint> #include <cstddef> namespace zawa { using i16 = std::int16_t; using i32 = std::int32_t; using i64 = std::int64_t; using i128 = __int128_t; using u8 = std::uint8_t; using u16 = std::uint16_t; using u32 = std::uint32_t; using u64 = std::uint64_t; using usize = std::size_t; } // namespace zawa #include <concepts> namespace zawa { namespace Concept { template <class T> concept Monoid = requires { typename T::Element; { T::identity() } -> std::same_as<typename T::Element>; { T::operation(std::declval<typename T::Element>(), std::declval<typename T::Element>()) } -> std::same_as<typename T::Element>; }; } // namespace } // namespace zawa namespace zawa { namespace Concept { template <class T> concept Inversible = requires { typename T::Element; { T::inverse(std::declval<typename T::Element>()) } -> std::same_as<typename T::Element>; }; template <class T> concept Group = Monoid<T> and Inversible<T>; } // namespace Concept } // namespace zawa #include <ostream> #include <functional> #include <type_traits> namespace zawa { template <Concept::Group Group> class FenwickTree { private: using Value = typename Group::Element; usize n_; u32 bitWidth_; std::vector<Value> a_, dat_; constexpr i32 lsb(i32 x) const noexcept { return x & -x; } // a[i] <- a[i] + v void addDat(i32 i, const Value& v) { assert(0 <= i and i < static_cast<i32>(n_)); for ( i++ ; i < static_cast<i32>(dat_.size()) ; i += lsb(i)) { dat_[i] = Group::operation(dat_[i], v); } } // return a[0] + a[1] + .. + a[i - 1] Value product(i32 i) const { assert(0 <= i and i <= static_cast<i32>(n_)); Value res{ Group::identity() }; for ( ; i > 0 ; i -= lsb(i)) { res = Group::operation(res, dat_[i]); } return res; } public: FenwickTree() : n_{}, bitWidth_{}, a_{}, dat_{} {} FenwickTree(usize n) : n_{ n }, bitWidth_{ std::__lg(static_cast<u32>(n)) + 1 }, a_(n), dat_(n + 1, Group::identity()) { dat_.shrink_to_fit(); } FenwickTree(const std::vector<Value>& a) : n_{ a.size() }, bitWidth_{ std::__lg(static_cast<u32>(a.size())) + 1 }, a_(a), dat_(a.size() + 1, Group::identity()) { dat_.shrink_to_fit(); for (i32 i{} ; i < static_cast<i32>(n_) ; i++) { addDat(i, a[i]); } } // return a[i] const Value& get(usize i) const noexcept { assert(i < n_); return a_[i]; } // return a[i] const Value& operator[](usize i) const noexcept { assert(i < n_); return a_[i]; } usize size() const noexcept { return n_; } // a[i] <- a[i] + v void operation(usize i, const Value& v) { assert(i < n_); addDat(i, v); a_[i] = Group::operation(a_[i], v); } // a[i] <- v void set(usize i, const Value& v) { assert(i < n_); addDat(i, Group::operation(Group::inverse(a_[i]), v)); a_[i] = v; } // return a[0] + a[1] + ... + a[r - 1] Value prefixProduct(usize r) const { assert(r <= n_); return product(r); } // return a[l] + a[l + 1] ... + a[r - 1] Value product(usize l, usize r) const { assert(l <= r and r <= n_); return Group::operation(Group::inverse(product(l)), product(r)); } template <class Function> u32 maxRight(usize l, const Function& f) const { static_assert(std::is_convertible_v<decltype(f), std::function<bool(Value)>>, "maxRight's argument f must be function bool(T)"); assert(l < n_); Value sum{ Group::inverse(product(l)) }; u32 r{}; for (u32 bit{ bitWidth_ } ; bit ; ) { bit--; u32 nxt{ r | (1u << bit) }; if (nxt < dat_.size() and f(Group::operation(sum, dat_[nxt]))) { sum = Group::operation(sum, dat_[nxt]); r = std::move(nxt); } } assert(l <= r); return r; } template <class Function> u32 minLeft(usize r, const Function& f) const { static_assert(std::is_convertible_v<decltype(f), std::function<bool(Value)>>, "minLeft's argument f must be function bool(T)"); assert(r <= n_); Value sum{ product(r) }; u32 l{}; for (u32 bit{ bitWidth_ } ; bit ; ) { bit--; u32 nxt{ l | (1u << bit) }; if (nxt <= r and not f(Group::operation(Group::inverse(dat_[nxt]), sum))) { sum = Group::operation(Group::inverse(dat_[nxt]), sum); l = std::move(nxt); } } assert(l <= r); return l; } // debug print friend std::ostream& operator<<(std::ostream& os, const FenwickTree& ft) { for (u32 i{} ; i <= ft.size() ; i++) { os << ft.prefixProduct(i) << (i == ft.size() ? "" : " "); } return os; } }; } // namespace zawa using namespace zawa; // #include "atcoder/modint" // using mint = atcoder::modint998244353; int Q, L[200020], R[200020], lpf[1000010]; std::vector<int> x[1000010], ord[1000010]; int main() { std::cin.tie(nullptr); std::cout.tie(nullptr); std::ios::sync_with_stdio(false); { // https://zawa-tin.github.io/cp-documentation/Src/Number/LinearSieve.hpp std::vector<int> p; for (int i = 2 ; i <= 1000000 ; i++) { if (!lpf[i]) { lpf[i] = i; p.push_back(i); } for (int v : p) { if ((long long)v * i > 1000000) break; lpf[v * i] = v; } } } x[0].push_back(1); for (int i = 2 ; i <= 1000000 ; i++) { assert(i % lpf[i] == 0); x[i / lpf[i]].push_back(i); } std::cin >> Q; for (int i = 0 ; i < Q ; i++) { std::cin >> L[i] >> R[i]; ord[L[i]].push_back(i); } FenwickTree<AdditiveGroup<int>> fen(1000001); std::vector<int> ans(Q); for (int i = 1 ; i <= 1000000 ; i++) { for (int idx : x[i - 1]) fen.operation(idx, 1); for (int idx : ord[i]) ans[idx] = fen.product(L[idx], R[idx] + 1); } for (int a : ans) std::cout << a << '\n'; }