結果

問題 No.2369 Some Products
ユーザー ebi_flyebi_fly
提出日時 2023-06-30 23:08:34
言語 C++17
(gcc 12.3.0 + boost 1.83.0)
結果
TLE  
実行時間 -
コード長 15,208 bytes
コンパイル時間 3,565 ms
コンパイル使用メモリ 201,680 KB
実行使用メモリ 207,004 KB
最終ジャッジ日時 2024-07-07 11:03:51
合計ジャッジ時間 7,110 ms
ジャッジサーバーID
(参考情報)
judge4 / judge5
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
13,752 KB
testcase_01 AC 1 ms
6,940 KB
testcase_02 TLE -
testcase_03 -- -
testcase_04 -- -
testcase_05 -- -
testcase_06 -- -
testcase_07 -- -
testcase_08 -- -
testcase_09 -- -
testcase_10 -- -
testcase_11 -- -
testcase_12 -- -
testcase_13 -- -
testcase_14 -- -
権限があれば一括ダウンロードができます

ソースコード

diff #

#line 1 "a.cpp"
#include <algorithm>
#include <bitset>
#include <cassert>
#include <chrono>
#include <climits>
#include <cmath>
#include <complex>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <memory>
#include <numeric>
#include <optional>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

/* macro */

#define rep(i, a, n) for (int i = (int)(a); i < (int)(n); i++)
#define rrep(i, a, n) for (int i = ((int)(n)-1); i >= (int)(a); i--)
#define Rep(i, a, n) for (i64 i = (i64)(a); i < (i64)(n); i++)
#define RRep(i, a, n) for (i64 i = ((i64)(n)-i64(1)); i >= (i64)(a); i--)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()

/* macro end */

/* template */

namespace ebi {

#ifdef LOCAL
#define debug(...)                                                      \
    std::cerr << "LINE: " << __LINE__ << "  [" << #__VA_ARGS__ << "]:", \
        debug_out(__VA_ARGS__)
#else
#define debug(...)
#endif

void debug_out() {
    std::cerr << std::endl;
}

template <typename Head, typename... Tail> void debug_out(Head h, Tail... t) {
    std::cerr << " " << h;
    if (sizeof...(t) > 0) std::cerr << " :";
    debug_out(t...);
}

template <typename T1, typename T2>
std::ostream &operator<<(std::ostream &os, const std::pair<T1, T2> &pa) {
    return os << pa.first << " " << pa.second;
}

template <typename T1, typename T2>
std::istream &operator>>(std::istream &os, std::pair<T1, T2> &pa) {
    return os >> pa.first >> pa.second;
}

template <typename T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &vec) {
    for (std::size_t i = 0; i < vec.size(); i++)
        os << vec[i] << (i + 1 == vec.size() ? "" : " ");
    return os;
}

template <typename T>
std::istream &operator>>(std::istream &os, std::vector<T> &vec) {
    for (T &e : vec) std::cin >> e;
    return os;
}

template <typename T>
std::ostream &operator<<(std::ostream &os, const std::optional<T> &opt) {
    if (opt) {
        os << opt.value();
    } else {
        os << "invalid value";
    }
    return os;
}

using std::size_t;
using i32 = std::int32_t;
using u32 = std::uint32_t;
using i64 = std::int64_t;
using u64 = std::uint64_t;
using i128 = __int128_t;
using u128 = __uint128_t;

template <class T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}

template <class T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}

template <class T> T pow(T x, i64 n) {
    T res = 1;
    while (n > 0) {
        if (n & 1) res = res * x;
        x = x * x;
        n >>= 1;
    }
    return res;
}

template <class T> struct Edge {
    int to;
    T cost;
    Edge(int _to, T _cost = 1) : to(_to), cost(_cost) {}
};

template <class T> struct Graph : std::vector<std::vector<Edge<T>>> {
    using std::vector<std::vector<Edge<T>>>::vector;
    void add_edge(int u, int v, T w, bool directed = false) {
        (*this)[u].emplace_back(v, w);
        if (directed) return;
        (*this)[v].emplace_back(u, w);
    }
};

struct graph : std::vector<std::vector<int>> {
    using std::vector<std::vector<int>>::vector;
    void add_edge(int u, int v, bool directed = false) {
        (*this)[u].emplace_back(v);
        if (directed) return;
        (*this)[v].emplace_back(u);
    }
};

constexpr i64 LNF = std::numeric_limits<i64>::max() / 4;

constexpr int INF = std::numeric_limits<int>::max() / 2;

const std::vector<int> dy = {1, 0, -1, 0, 1, 1, -1, -1};
const std::vector<int> dx = {0, 1, 0, -1, 1, -1, 1, -1};

}  // namespace ebi

#line 2 "fps/fps.hpp"

#line 7 "fps/fps.hpp"

namespace ebi {

template <class mint, std::vector<mint> (*convolution)(
                          const std::vector<mint> &, const std::vector<mint> &)>
struct FormalPowerSeries : std::vector<mint> {
  private:
    using std::vector<mint>::vector;
    using std::vector<mint>::vector::operator=;
    using FPS = FormalPowerSeries;

  public:
    FPS operator+(const FPS &rhs) const noexcept {
        return FPS(*this) += rhs;
    }
    FPS operator-(const FPS &rhs) const noexcept {
        return FPS(*this) -= rhs;
    }
    FPS operator*(const FPS &rhs) const noexcept {
        return FPS(*this) *= rhs;
    }
    FPS operator/(const FPS &rhs) const noexcept {
        return FPS(*this) /= rhs;
    }
    FPS operator%(const FPS &rhs) const noexcept {
        return FPS(*this) %= rhs;
    }

    FPS operator+(const mint &rhs) const noexcept {
        return FPS(*this) += rhs;
    }
    FPS operator-(const mint &rhs) const noexcept {
        return FPS(*this) -= rhs;
    }
    FPS operator*(const mint &rhs) const noexcept {
        return FPS(*this) *= rhs;
    }
    FPS operator/(const mint &rhs) const noexcept {
        return FPS(*this) /= rhs;
    }

    FPS &operator+=(const FPS &rhs) noexcept {
        if (this->size() < rhs.size()) this->resize(rhs.size());
        for (int i = 0; i < (int)rhs.size(); ++i) {
            (*this)[i] += rhs[i];
        }
        return *this;
    }

    FPS &operator-=(const FPS &rhs) noexcept {
        if (this->size() < rhs.size()) this->resize(rhs.size());
        for (int i = 0; i < (int)rhs.size(); ++i) {
            (*this)[i] -= rhs[i];
        }
        return *this;
    }

    FPS &operator*=(const FPS &rhs) noexcept {
        *this = convolution(*this, rhs);
        return *this;
    }

    FPS &operator/=(const FPS &rhs) noexcept {
        int n = deg() - 1;
        int m = rhs.deg() - 1;
        if (n < m) {
            *this = {};
            return *this;
        }
        *this = (*this).rev() * rhs.rev().inv(n - m + 1);
        (*this).resize(n - m + 1);
        std::reverse((*this).begin(), (*this).end());
        return *this;
    }

    FPS &operator%=(const FPS &rhs) noexcept {
        *this -= *this / rhs * rhs;
        shrink();
        return *this;
    }

    FPS &operator+=(const mint &rhs) noexcept {
        if (this->empty()) this->resize(1);
        (*this)[0] += rhs;
        return *this;
    }

    FPS &operator-=(const mint &rhs) noexcept {
        if (this->empty()) this->resize(1);
        (*this)[0] -= rhs;
        return *this;
    }

    FPS &operator*=(const mint &rhs) noexcept {
        for (int i = 0; i < deg(); ++i) {
            (*this)[i] *= rhs;
        }
        return *this;
    }
    FPS &operator/=(const mint &rhs) noexcept {
        mint inv_rhs = rhs.inv();
        for (int i = 0; i < deg(); ++i) {
            (*this)[i] *= inv_rhs;
        }
        return *this;
    }

    FPS operator>>(int d) const {
        if (deg() <= d) return {};
        FPS f = *this;
        f.erase(f.begin(), f.begin() + d);
        return f;
    }

    FPS operator<<(int d) const {
        FPS f = *this;
        f.insert(f.begin(), d, 0);
        return f;
    }

    FPS operator-() const {
        FPS g(this->size());
        for (int i = 0; i < (int)this->size(); i++) g[i] = -(*this)[i];
        return g;
    }

    FPS pre(int sz) const {
        return FPS(this->begin(), this->begin() + std::min(deg(), sz));
    }

    FPS rev() const {
        auto f = *this;
        std::reverse(f.begin(), f.end());
        return f;
    }

    FPS differential() const {
        int n = deg();
        FPS g(std::max(0, n - 1));
        for (int i = 0; i < n - 1; i++) {
            g[i] = (*this)[i + 1] * (i + 1);
        }
        return g;
    }

    FPS integral() const {
        int n = deg();
        FPS g(n + 1);
        g[0] = 0;
        if (n > 0) g[1] = 1;
        auto mod = mint::mod();
        for (int i = 2; i <= n; i++) g[i] = (-g[mod % i]) * (mod / i);
        for (int i = 0; i < n; i++) g[i + 1] *= (*this)[i];
        return g;
    }

    FPS inv(int d = -1) const {
        int n = 1;
        if (d < 0) d = deg();
        FPS g(n);
        g[0] = (*this)[0].inv();
        while (n < d) {
            n <<= 1;
            g = (g * 2 - g * g * this->pre(n)).pre(n);
        }
        g.resize(d);
        return g;
    }

    FPS log(int d = -1) const {
        assert((*this)[0].val() == 1);
        if (d < 0) d = deg();
        return ((*this).differential() * (*this).inv(d)).pre(d - 1).integral();
    }

    FPS exp(int d = -1) const {
        assert((*this)[0].val() == 0);
        int n = 1;
        if (d < 0) d = deg();
        FPS g(n);
        g[0] = 1;
        while (n < d) {
            n <<= 1;
            g = (g * (this->pre(n) - g.log(n) + 1)).pre(n);
        }
        g.resize(d);
        return g;
    }

    FPS pow(int64_t k, int d = -1) const {
        const int n = deg();
        if (d < 0) d = n;
        if (k == 0) {
            FPS f(d);
            if (d > 0) f[0] = 1;
            return f;
        }
        for (int i = 0; i < n; i++) {
            if ((*this)[i] != 0) {
                mint rev = (*this)[i].inv();
                FPS f = (((*this * rev) >> i).log(d) * k).exp(d);
                f *= (*this)[i].pow(k);
                f = (f << (i * k)).pre(d);
                if (f.deg() < d) f.resize(d);
                return f;
            }
            if (i + 1 >= (d + k - 1) / k) break;
        }
        return FPS(d);
    }

    int deg() const {
        return (*this).size();
    }

    void shrink() {
        while ((!this->empty()) && this->back() == 0) this->pop_back();
    }

    int count_terms() const {
        int c = 0;
        for (int i = 0; i < deg(); i++) {
            if ((*this)[i] != 0) c++;
        }
        return c;
    }

    std::optional<FPS> sqrt(int d = -1) const;
};

}  // namespace ebi
#line 2 "fps/fps_sparse.hpp"

#line 5 "fps/fps_sparse.hpp"

#line 2 "utility/modint_func.hpp"

#line 5 "utility/modint_func.hpp"

namespace ebi {

template <class mint> mint inv(int n) {
    static const int mod = mint::mod();
    static std::vector<mint> dat = {0, 1};
    assert(0 <= n);
    if (n >= mod) n -= mod;
    while (int(dat.size()) <= n) {
        int num = dat.size();
        int q = (mod + num - 1) / num;
        dat.emplace_back(dat[num * q - mod] * mint(q));
    }
    return dat[n];
}

}  // namespace ebi
#line 7 "fps/fps_sparse.hpp"

namespace ebi {

template <class mint>
std::vector<mint> mul_sparse(const std::vector<mint> &f,
                             const std::vector<mint> &g) {
    int n = f.size();
    int m = g.size();
    std::vector<std::pair<int, mint>> cf, cg;
    for (int i = 0; i < n; i++) {
        if (f[i] != 0) cf.emplace_back(i, f[i]);
    }
    for (int i = 0; i < m; i++) {
        if (g[i] != 0) cg.emplace_back(i, g[i]);
    }
    std::vector<mint> h(n + m - 1);
    for (auto [i, p] : cf) {
        for (auto [j, q] : cg) {
            h[i + j] += p * q;
        }
    }
    return h;
}

template <class mint>
std::vector<mint> inv_sparse(const std::vector<mint> &f, int d = -1) {
    assert(f[0] != 0);
    if (d < 0) {
        d = f.size();
    }
    std::vector<std::pair<int, mint>> ret;
    for (int i = 1; i < int(f.size()); i++) {
        if (f[i] != 0) {
            ret.emplace_back(i, f[i]);
        }
    }
    std::vector<mint> g(d);
    g[0] = f[0].inv();
    for (int i = 1; i < d; i++) {
        for (auto [k, p] : ret) {
            if (i - k < 0) break;
            g[i] -= g[i - k] * p;
        }
        g[i] *= g[0];
    }
    return g;
}

template <class mint>
std::vector<mint> exp_sparse(const std::vector<mint> &f, int d = -1) {
    int n = f.size();
    if (d < 0) d = n;
    std::vector<std::pair<int, mint>> ret;
    for (int i = 1; i < n; i++) {
        if (f[i] != 0) {
            ret.emplace_back(i - 1, f[i] * i);
        }
    }
    std::vector<mint> g(d);
    g[0] = 1;
    for (int i = 0; i < d - 1; i++) {
        for (auto [k, p] : ret) {
            if (i - k < 0) break;
            g[i + 1] += g[i - k] * p;
        }
        g[i + 1] *= inv<mint>(i + 1);
    }
    return g;
}

template <class mint>
std::vector<mint> log_sparse(const std::vector<mint> &f, int d = -1) {
    int n = f.size();
    if (d < 0) d = n;
    std::vector<mint> df(d);
    for (int i = 0; i < std::min(d, n - 1); i++) {
        df[i] = f[i + 1] * (i + 1);
    }
    auto dg = mul_sparse(df, inv_sparse(f));
    dg.resize(d);
    std::vector<mint> g(d);
    for (int i = 0; i < d - 1; i++) {
        g[i + 1] = dg[i] * inv<mint>(i + 1);
    }
    return g;
}

template <class mint>
std::vector<mint> pow_sparse_1(const std::vector<mint> &f, long long k,
                               int d = -1) {
    int n = f.size();
    assert(n == 0 || f[0] == 1);
    std::vector<std::pair<int, mint>> ret;
    for (int i = 1; i < n; i++) {
        if (f[i] != 0) ret.emplace_back(i, f[i]);
    }
    std::vector<mint> g(d);
    g[0] = 1;
    for (int i = 0; i < d - 1; i++) {
        for (const auto &[j, cf] : ret) {
            if (i + 1 - j < 0) break;
            g[i + 1] +=
                (mint(k) * mint(j) - mint(i - j + 1)) * cf * g[i + 1 - j];
        }
        g[i + 1] *= inv<mint>(i + 1);
    }
    return g;
}

template <class mint>
std::vector<mint> pow_sparse(const std::vector<mint> &f, long long k,
                             int d = -1) {
    int n = f.size();
    if (d < 0) d = n;
    assert(k >= 0);
    if (k == 0) {
        std::vector<mint> g(d);
        if (d > 0) g[0] = 1;
        return g;
    }
    for (int i = 0; i < n; i++) {
        if (f[i] != 0) {
            mint rev = f[i].inv();
            std::vector<mint> f2(n - i);
            for (int j = i; j < n; j++) {
                f2[j - i] = f[j] * rev;
            }
            f2 = pow_sparse_1(f2, k, d);
            mint fk = f[i].pow(k);
            std::vector<mint> g(d);
            for (int j = 0; j < int(f2.size()); j++) {
                if (j + i * k >= d) break;
                g[j + i * k] = f2[j] * fk;
            }
            return g;
        }
        if (i >= (d + k - 1) / k) break;
    }
    return std::vector<mint>(d);
}

}  // namespace ebi
#line 167 "a.cpp"

#include <atcoder/convolution>
#include <atcoder/segtree>
#include <atcoder/modint>

namespace ebi {

using mint = atcoder::modint998244353;

using FPS = FormalPowerSeries<mint, atcoder::convolution>;

FPS op(FPS lhs, FPS rhs) {
    return lhs + rhs;
}

FPS e() {
    return {0};
}

void main_() {
    int n;
    std::cin >> n;
    atcoder::segtree<FPS, op, e> seg(n);
    rep(i,0,n) {
        i64 p;
        std::cin >> p;
        std::vector<mint> f(n+1);
        f[0] = 1;
        f[1] = p;
        f = log_sparse(f, n+1);
        FPS g(n+1);
        rep(i,0,n+1) g[i] = f[i];
        seg.set(i, g);
    }
    int q;
    std::cin >> q;
    while(q--) {
        int a,b,k;
        std::cin >> a >> b >> k;
        a--;
        std::cout << seg.prod(a, b).exp(k + 1)[k].val() << '\n';
    }
}

}  // namespace ebi

int main() {
    std::cout << std::fixed << std::setprecision(15);
    std::cin.tie(nullptr);
    std::ios::sync_with_stdio(false);
    int t = 1;
    // std::cin >> t;
    while (t--) {
        ebi::main_();
    }
    return 0;
}
0