This documentation is automatically generated by online-judge-tools/verification-helper
View the Project on GitHub suisen-cp/cp-library-cpp
#define PROBLEM "https://atcoder.jp/contests/abc230/tasks/abc230_h" #include <iostream> #include <atcoder/modint> #include <atcoder/convolution> using mint = atcoder::modint998244353; #include "library/math/inv_mods.hpp" #include "library/convolution/relaxed_convolution.hpp" int main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int n, m; std::cin >> n >> m; std::vector<mint> c(n + 1); for (int i = 0; i < m; ++i) { int w; std::cin >> w; c[w] = 1; } suisen::inv_mods<mint> invs(n); suisen::RelaxedConvolution<mint> h{ [](const auto& f, const auto &g) { return atcoder::convolution(f, g); } }; std::vector<mint> f(n), g(n); for (int w = 1; w < n; ++w) { for (int i = 1; i * w - 1 < n; ++i) { g[i * w - 1] += w * (f[w - 1] + c[w]); } f[w] = h.append((w == 1) + f[w - 1], g[w - 1]) * invs[w]; } f.erase(f.begin()); for (const auto &e : f) { std::cout << e.val() << '\n'; } return 0; }
#line 1 "test/src/convolution/relaxed_convolution/abc230_h.test.cpp" #define PROBLEM "https://atcoder.jp/contests/abc230/tasks/abc230_h" #include <iostream> #include <atcoder/modint> #include <atcoder/convolution> using mint = atcoder::modint998244353; #line 1 "library/math/inv_mods.hpp" #include <vector> namespace suisen { template <typename mint> class inv_mods { public: inv_mods() = default; inv_mods(int n) { ensure(n); } const mint& operator[](int i) const { ensure(i); return invs[i]; } static void ensure(int n) { int sz = invs.size(); if (sz < 2) invs = { 0, 1 }, sz = 2; if (sz < n + 1) { invs.resize(n + 1); for (int i = sz; i <= n; ++i) invs[i] = mint(mod - mod / i) * invs[mod % i]; } } private: static std::vector<mint> invs; static constexpr int mod = mint::mod(); }; template <typename mint> std::vector<mint> inv_mods<mint>::invs{}; template <typename mint> std::vector<mint> get_invs(const std::vector<mint>& vs) { const int n = vs.size(); mint p = 1; for (auto& e : vs) { p *= e; assert(e != 0); } mint ip = p.inv(); std::vector<mint> rp(n + 1); rp[n] = 1; for (int i = n - 1; i >= 0; --i) { rp[i] = rp[i + 1] * vs[i]; } std::vector<mint> res(n); for (int i = 0; i < n; ++i) { res[i] = ip * rp[i + 1]; ip *= vs[i]; } return res; } } #line 1 "library/convolution/relaxed_convolution.hpp" #line 5 "library/convolution/relaxed_convolution.hpp" namespace suisen { // reference: https://qiita.com/Kiri8128/items/1738d5403764a0e26b4c template <typename T> struct RelaxedConvolution { using value_type = T; using polynomial_type = std::vector<value_type>; using convolution_type = polynomial_type(*)(const polynomial_type&, const polynomial_type&); RelaxedConvolution() = default; RelaxedConvolution(const convolution_type &convolve) : _convolve(convolve), _n(0), _f{}, _g{}, _h{} {} void set_convolve_function(const convolution_type &convolve) { _convolve = convolve; } value_type append(const value_type &fi, const value_type &gi) { ++_n; _f.push_back(fi), _g.push_back(gi); for (int p = 1;; p <<= 1) { int l1 = _n - p, r1 = _n, l2 = p - 1, r2 = l2 + p; add(l1 + l2, range_convolve(l1, r1, l2, r2)); if (l1 == l2) break; add(l1 + l2, range_convolve(l2, r2, l1, r1)); if (not (_n & p)) break; } return _h[_n - 1]; } const value_type& operator[](int i) const { return _h[i]; } polynomial_type get() const { return _h; } private: convolution_type _convolve = [](const polynomial_type&, const polynomial_type&) -> polynomial_type { assert(false); }; int _n; polynomial_type _f, _g, _h; polynomial_type range_convolve(int l1, int r1, int l2, int r2) { return _convolve(polynomial_type(_f.begin() + l1, _f.begin() + r1), polynomial_type(_g.begin() + l2, _g.begin() + r2)); } void add(std::size_t bias, const polynomial_type &h) { if (_h.size() < bias + h.size()) _h.resize(bias + h.size()); for (std::size_t i = 0; i < h.size(); ++i) _h[bias + i] += h[i]; } }; } // namespace suisen #line 12 "test/src/convolution/relaxed_convolution/abc230_h.test.cpp" int main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int n, m; std::cin >> n >> m; std::vector<mint> c(n + 1); for (int i = 0; i < m; ++i) { int w; std::cin >> w; c[w] = 1; } suisen::inv_mods<mint> invs(n); suisen::RelaxedConvolution<mint> h{ [](const auto& f, const auto &g) { return atcoder::convolution(f, g); } }; std::vector<mint> f(n), g(n); for (int w = 1; w < n; ++w) { for (int i = 1; i * w - 1 < n; ++i) { g[i * w - 1] += w * (f[w - 1] + c[w]); } f[w] = h.append((w == 1) + f[w - 1], g[w - 1]) * invs[w]; } f.erase(f.begin()); for (const auto &e : f) { std::cout << e.val() << '\n'; } return 0; }