結果

問題 No.1145 Sums of Powers
ユーザー Yuki-Wada
提出日時 2025-01-23 20:42:36
言語 C++17(gcc12)
(gcc 12.3.0 + boost 1.87.0)
結果
WA  
実行時間 -
コード長 18,099 bytes
コンパイル時間 16,446 ms
コンパイル使用メモリ 239,020 KB
実行使用メモリ 58,288 KB
最終ジャッジ日時 2025-01-23 20:42:59
合計ジャッジ時間 23,496 ms
ジャッジサーバーID
(参考情報)
judge1 / judge4
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
other WA * 5 TLE * 1
権限があれば一括ダウンロードができます

ソースコード

diff #

// include
//------------------------------------------
#include <string>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>

#include <numeric>
#include <utility>
#include <complex>

#include <sstream>
#include <iostream>
#include <iomanip>

#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <ctime>

// namespace
using namespace std;

// temporary
#include <atcoder/all>
using namespace atcoder;

// print
#define RET(x) return cout << x << endl, 0;

// for loop
#define REP(i, a, b) for ((i) = (ll)(a); (i) < (ll)(b); (i)++)
#define REPD(i, a, b) for (ll i = (ll)(a); (i) < (ll)(b); (i)++)
#define REPI(v, vs) for (auto &v : vs)

// debug
#ifdef LOCAL_ENV
#define DUMP(x) cerr << #x << " = " << (x) << endl
#define DEBUG(x) cerr << #x << " = " << (x) << " (l" << __LINE__ << ")" \
                      << " " << __FILE__ << endl
#else
#define DUMP(x)
#define DEBUG(x)
#endif

#define MAX_VALUE 9223372036854775807LL

// type alias
using ll = long long;
using ull = unsigned long long;
using comp = complex<double>;
using llpair = pair<ll, ll>;
template <class T>
using vector2d = vector<vector<T>>;
template <class T>
using vector3d = vector<vector<vector<T>>>;
using ll1d = vector<ll>;
using ll2d = vector2d<ll>;
using ll3d = vector3d<ll>;

// constant
static constexpr ll MOD = 998244353LL;
constexpr ll MOD_PRIMITIVE_ROOT = 3LL;
constexpr ll MOD_INVERSE_PRIMITIVE_ROOT = 332748118LL;
static constexpr double PI = 3.14159265358979323846;

template <ull N, class T, class... Args, std::enable_if_t<N == 0, int> = 0>
auto make_multiple_vector(Args... args)
{
    return T(args...);
}

template <ull N, class T, class... Args, std::enable_if_t<N != 0, int> = 0>
auto make_multiple_vector(ull size, Args... args)
{
    using value_type = std::decay_t<decltype(make_multiple_vector<N - 1, T>(args...))>;
    return vector<value_type>(size, make_multiple_vector<N - 1, T>(args...));
}

using rll = atcoder::modint998244353;

inline ull get_power2_more_than_input(ull input)
{
    // val is 0.
    if (input == 0ULL)
        return 1ULL;
    // val is power of 2
    if (!(input & (input - 1)))
        return input;

    ull highest_one_bit = input;
    while ((highest_one_bit & (highest_one_bit - 1LL)) != 0)
        highest_one_bit = highest_one_bit & (highest_one_bit - 1LL);
    ull power2 = highest_one_bit << 1LL;
    return power2;
}

inline ull get_value_more_than_log_2_input(ull input)
{
    auto get_power2 = [](ull input)
    {
        // val is 0.
        if (input == 0ULL)
            return 1ULL;
        // val is power of 2
        if (!(input & (input - 1)))
            return input;

        ull highest_one_bit = input;
        while ((highest_one_bit & (highest_one_bit - 1LL)) != 0)
            highest_one_bit = highest_one_bit & (highest_one_bit - 1LL);
        ull power2 = highest_one_bit << 1LL;
        return power2;
    };

    auto power2 = get_power2(input);
    ull value = 0ULL;
    while (power2 > 1ULL)
    {
        power2 >>= 1LL;
        ++value;
    }
    return value;
}

// Fast Modulo Transform
vector<rll> fmt_impl(const vector<rll> &function, const rll primitive_root)
{
    ll degree = function.size();
    if (degree == 0LL)
        throw runtime_error("配列の要素数は 1 以上である必要があります。");
    if ((degree & (degree - 1LL)) != 0LL)
        throw runtime_error("配列の要素数は 2 のべき乗である必要があります。");

    auto get_power2 = [&](rll base, ull exponential)
    {
        rll result = 1;
        while (exponential >= 1)
        {
            if (exponential & 1)
            {
                result = result * base;
            }
            base = base * base;
            exponential >>= 1;
        }

        return result;
    };
    rll xi = get_power2(rll(primitive_root), (MOD - 1LL) / degree);

    vector<rll> transformed(degree, 0);
    vector<rll> stored(degree, 0);

    for (ll i = 0; i < degree; ++i)
        transformed[i] = function[i];
    if (degree == 1LL)
    {
        return transformed;
    }

    ll log_2_deg = 0LL;
    for (ll i = 1; i < degree; i <<= 1LL)
        ++log_2_deg;

    vector<rll> mod_xi_2s(log_2_deg);
    vector<ll> power_2s(log_2_deg);
    mod_xi_2s[0] = xi, power_2s[0] = 1LL;
    for (ll i = 1; i < log_2_deg; ++i)
        mod_xi_2s[i] = mod_xi_2s[i - 1LL] * mod_xi_2s[i - 1LL], power_2s[i] = 1LL << i;

    for (ll e = 0; e < log_2_deg; ++e)
    {
        auto mod_xi = mod_xi_2s[log_2_deg - e - 1LL];
        auto skip = power_2s[log_2_deg - e - 1LL];
        for (ll i = 0; i < degree; ++i)
            stored[i] = transformed[i];

        rll power_of_xi = 1;
        for (ll i = 0; i < (degree / skip); ++i)
        {
            for (ll start = 0; start < skip; ++start)
            {
                auto idx = start + skip * i;
                auto res_i = i % (degree / skip / 2LL);

                auto stored_idx = start + skip * res_i * 2LL;
                transformed[idx] = stored[stored_idx] + stored[stored_idx + skip] * power_of_xi;
            }
            power_of_xi = power_of_xi * mod_xi;
        }
    }
    return transformed;
}

vector<rll> fmt(const vector<rll> &function)
{
    vector<rll> transformed = fmt_impl(function, MOD_PRIMITIVE_ROOT);
    return transformed;
}

vector<rll> inv_fmt(const vector<rll> &function)
{
    vector<rll> transformed = fmt_impl(function, MOD_INVERSE_PRIMITIVE_ROOT);
    auto inverse_n = rll(1) / rll(function.size());
    for (unsigned int i = 0; i < function.size(); ++i)
        transformed[i] = transformed[i] * inverse_n;

    return transformed;
}

vector<rll> fmt_convolution(const vector<rll> &a, const vector<rll> &b)
{
    unsigned int coef_num = a.size() + b.size() - 1U;
    unsigned int fmt_size = get_power2_more_than_input(coef_num);

    vector<rll> rll_a(fmt_size);
    vector<rll> rll_b(fmt_size);
    for (unsigned int i = 0; i < a.size(); ++i)
        rll_a[i] = a[i];
    for (unsigned int i = 0; i < b.size(); ++i)
        rll_b[i] = b[i];

    auto fmt_a = fmt(rll_a);
    auto fmt_b = fmt(rll_b);
    vector<rll> fmt_ab(fmt_size);
    for (unsigned int i = 0; i < fmt_size; ++i)
        fmt_ab[i] = fmt_a[i] * fmt_b[i];

    auto rll_ab = inv_fmt(fmt_ab);

    return rll_ab;
}

vector<rll> my_convolution(const vector<rll> &a, const vector<rll> &b)
{
    return fmt_convolution(a, b);
}

template <class Number>
class Polynomial
{
private:
public:
    vector<Number> coefs;

    Polynomial() : coefs(1U) {}
    Polynomial(Number constant) : coefs(1U, constant) {}
    Polynomial(vector<Number> coefs) : coefs(coefs) {}

    static Polynomial zero_polynomial(unsigned int coef_num)
    {
        vector<Number> coefs(coef_num);
        return Polynomial(coefs);
    }

    Number operator[](unsigned int n) const
    {
        return (n < coefs.size() ? coefs[n] : Number(0));
    }
    Number &operator[](unsigned int n)
    {
        if (n >= coefs.size())
            coefs.resize(n + 1U);

        return coefs[n];
    }
    unsigned int coef_num() const { return coefs.size(); }
    Number operator()(Number point) const
    {
        unsigned int N = coef_num();
        Number result = 0;
        Number point_power = 1;
        for (unsigned int i = 0; i < N; ++i)
        {
            result = result + coefs[i] * point_power;
            point_power = point_power * point;

            result = mod_red(result);
            point_power = mod_red(point_power);
        }

        return result;
    }

    void resize(unsigned int n) { coefs.resize(n); }
    void mod_xn(unsigned int n) { coefs.resize(n); }
    void zero_trim()
    {
        unsigned int N = coef_num();
        unsigned int max_coef_idx = 1;
        for (unsigned int i = 0; i < N; ++i)
            if (coefs[N - i - 1U] != 0)
            {
                max_coef_idx = N - i;
                break;
            }

        coefs.resize(max_coef_idx);
    }
};

template <class Number>
Polynomial<Number> operator+(const Polynomial<Number> &lhs, const Polynomial<Number> &rhs)
{
    unsigned int coef_num = max(lhs.coef_num(), rhs.coef_num());
    auto outputs = Polynomial<Number>::zero_polynomial(coef_num);
    for (unsigned int i = 0; i < coef_num; ++i)
    {
        outputs[i] = 0;
        if (i < lhs.coef_num())
            outputs[i] += lhs[i];
        if (i < rhs.coef_num())
            outputs[i] += rhs[i];
    }
    return outputs;
}

template <class Number>
Polynomial<Number> operator+(const Polynomial<Number> &lhs, Number rhs)
{
    unsigned int coef_num = lhs.coef_num();
    auto outputs = Polynomial<Number>::zero_polynomial(coef_num);
    outputs[0] = rhs;
    for (unsigned int i = 0; i < coef_num; ++i)
        outputs[i] = outputs[i] + lhs[i];
    return {outputs};
}

template <class Number>
Polynomial<Number> operator+(Number lhs, const Polynomial<Number> &rhs)
{
    unsigned int coef_num = rhs.coef_num();
    auto outputs = Polynomial<Number>::zero_polynomial(coef_num);
    outputs[0] = lhs;
    for (unsigned int i = 0; i < coef_num; ++i)
        outputs[i] = outputs[i] + rhs[i];
    return {outputs};
}

template <class Number>
Polynomial<Number> operator-(const Polynomial<Number> &lhs, const Polynomial<Number> &rhs)
{
    unsigned int coef_num = max(lhs.coef_num(), rhs.coef_num());
    auto output = Polynomial<Number>::zero_polynomial(coef_num);
    for (unsigned int i = 0; i < coef_num; ++i)
    {
        output[i] = 0;
        if (i < lhs.coef_num())
            output[i] = output[i] + lhs[i];
        if (i < rhs.coef_num())
            output[i] = output[i] - rhs[i];
    }
    return output;
}

template <class Number>
Polynomial<Number> operator-(const Polynomial<Number> &lhs, Number rhs)
{
    unsigned int coef_num = lhs.coef_num();
    auto outputs = Polynomial<Number>::zero_polynomial(coef_num);
    outputs[0] = -rhs;
    for (unsigned int i = 0; i < coef_num; ++i)
        outputs[i] += lhs[i];
    return {outputs};
}

template <class Number>
Polynomial<Number> operator-(Number lhs, const Polynomial<Number> &rhs)
{
    unsigned int coef_num = rhs.coef_num();
    auto outputs = Polynomial<Number>::zero_polynomial(coef_num);
    outputs[0] = lhs;
    for (unsigned int i = 0; i < coef_num; ++i)
        outputs[i] -= rhs[i];
    return {outputs};
}

template <class Number>
Polynomial<Number> operator-(const Polynomial<Number> &original)
{
    unsigned int coef_num = original.coef_num();
    auto outputs = Polynomial<Number>::zero_polynomial(coef_num);
    for (unsigned int i = 0; i < coef_num; ++i)
    {
        outputs[i] = 0;
        outputs[i] -= original[i];
    }
    return {outputs};
}

template <class Number>
Polynomial<Number> operator*(const Polynomial<Number> &lhs, const Polynomial<Number> &rhs)
{
    // Polynomial<Number> output(atcoder::convolution<MOD>(lhs.coefs, rhs.coefs));
    Polynomial<Number> output(my_convolution(lhs.coefs, rhs.coefs));
    return output;
}

template <class Number>
Polynomial<Number> derivative_f(const Polynomial<Number> &f)
{
    unsigned int coef_num = f.coef_num();
    auto diff_f = Polynomial<Number>::zero_polynomial(max(1U, coef_num - 1U));
    for (unsigned int i = 1; i < coef_num; i++)
        diff_f[i - 1] = f[i] * Number(i);
    return diff_f;
}

template <class Number>
Polynomial<Number> integral_f(const Polynomial<Number> &f)
{
    unsigned int coef_num = f.coef_num();
    auto integral_f = Polynomial<Number>::zero_polynomial(coef_num);
    for (unsigned int i = 0; i < coef_num; i++)
        integral_f[i + 1] = f[i] * Number(i + 1U);
    return integral_f;
}

template <class Number>
Polynomial<Number> inv(const Polynomial<Number> &f, unsigned int exponent)
{
    Polynomial<Number> gn(Number(1) / f[0]), truncated_f(f[0]);

    for (unsigned int e = 0; e < exponent; e++)
    {
        auto curr_pow = 1LL << e;
        auto next_pow = 1LL << (e + 1U);

        for (unsigned int i = curr_pow; i < next_pow; ++i)
            if (f[i] != 0)
                truncated_f[i] = f[i];
        auto gg = gn * gn;
        gg.mod_xn(next_pow);
        auto ggf = gg * truncated_f;

        for (unsigned int i = 0; i < next_pow; ++i)
            gn[i] = gn[i] * 2LL - ggf[i];
    }
    return gn;
}

template <class Number>
Polynomial<Number> log(const Polynomial<Number> &f, unsigned int exponent)
{
    auto pow = 1LL << exponent;
    auto inv_f = inv(f, exponent);
    auto diff_f = derivative_f(f);
    auto integrand = inv_f * diff_f;
    integrand.mod_xn(pow);
    auto int_f = integral_f(integrand);
    return int_f;
}

template <class Number>
Polynomial<Number> operator/(const Polynomial<Number> &lhs, const Polynomial<Number> &rhs)
{
    auto reverse_polynomial = [](const Polynomial<Number> &poly)
    {
        unsigned int LN = poly.coef_num();
        vector<Number> poly_rev_coefs;
        poly_rev_coefs.reserve(LN);
        for (unsigned int i = 0; i < LN; ++i)
        {
            auto poly_coef = poly[LN - i - 1U];
            poly_rev_coefs.emplace_back(poly_coef);
        }
        return Polynomial<Number>(poly_rev_coefs);
    };
    auto trim_and_reverse_polynomial = [](const Polynomial<Number> &poly)
    {
        unsigned int LN = poly.coef_num();
        vector<Number> poly_rev_coefs;
        for (unsigned int i = 0; i < LN; ++i)
        {
            auto poly_coef = poly[LN - i - 1U];
            if (poly_rev_coefs.size() == 0)
            {
                if (poly_coef != 0)
                    poly_rev_coefs.reserve(LN - i);
                else
                    continue;
            }
            poly_rev_coefs.emplace_back(poly_coef);
        }
        return Polynomial<Number>(poly_rev_coefs);
    };

    auto lhs_rev = trim_and_reverse_polynomial(lhs);
    auto rhs_rev = trim_and_reverse_polynomial(rhs);

    auto lhs_rev_coef_num = lhs_rev.coef_num();
    auto rhs_rev_coef_num = rhs_rev.coef_num();
    if (lhs_rev_coef_num < rhs_rev_coef_num)
        return {0};

    auto diff_coef_num = lhs_rev_coef_num - rhs_rev_coef_num + 1U;
    ll exponent = 0;
    ull n = diff_coef_num;
    while (n != 0)
    {
        exponent++;
        n >>= 1LL;
    }

    auto rev_q = Polynomial<Number>(lhs_rev) * inv(Polynomial<Number>(rhs_rev), exponent);
    rev_q.mod_xn(diff_coef_num);
    auto q = reverse_polynomial(rev_q);

    return q;
}

template <class Number>
Polynomial<Number> operator%(const Polynomial<Number> &lhs, const Polynomial<Number> &rhs)
{
    auto q = lhs / rhs;
    auto r = lhs - rhs * q;
    auto r_coef_num = r.coef_num();
    if (rhs.coef_num() >= 2U)
        r_coef_num = min(r_coef_num, rhs.coef_num() - 1U);
    r.mod_xn(r_coef_num);
    return r;
}

template <class Number>
Polynomial<Number> exp(const Polynomial<Number> &f, unsigned int exponent)
{
    Polynomial<Number> gn(1), truncated_f(f[0]);
    for (unsigned int e = 0; e < exponent; e++)
    {
        auto curr_pow = 1LL << e;
        auto next_pow = 1LL << (e + 1U);
        for (unsigned int i = curr_pow; i < next_pow; ++i)
            if (f[i] != 0)
                truncated_f[i] = f[i];

        auto gf = gn * truncated_f;
        auto log_g = log(gn, e + 1U);
        log_g.mod_xn(next_pow);
        auto g_log_g = gn * log_g;

        for (unsigned int i = 0; i < next_pow; ++i)
            gn[i] = Polynomial<Number>::mod_red(gf[i] + gn[i] - g_log_g[i]);
    }
    return gn;
}

template <class Number>
pair<Polynomial<Number>, Polynomial<Number>> prod(const vector<Polynomial<Number>> &polys)
{
    struct NodeInfo
    {
        ll left_idx;
        ll right_idx;
        ll size;
        Polynomial<Number> numerator;
        Polynomial<Number> denominator;
        NodeInfo(
            ll left_idx,
            ll right_idx,
            ll size,
            Polynomial<Number> numerator,
            Polynomial<Number> denominator) : left_idx(left_idx), right_idx(right_idx), size(size), numerator(numerator), denominator(denominator) {}
    };

    vector<NodeInfo> node_infos;
    queue<ll> node_queue;
    ll node_idx = 0;
    for (unsigned int i = 0; i < polys.size(); ++i)
    {
        node_infos.emplace_back(-1LL, -1LL, 1LL, Polynomial<Number>(1), polys[i]);
        node_queue.emplace(node_idx);
        ++node_idx;
    }
    while (true)
    {
        if (node_queue.empty())
            break;
        auto i1 = node_queue.front();
        node_queue.pop();
        if (node_queue.empty())
            break;
        auto i2 = node_queue.front();
        node_queue.pop();

        auto size1 = node_infos[i1].size;
        auto size2 = node_infos[i2].size;
        auto numerator1 = node_infos[i1].numerator;
        auto numerator2 = node_infos[i2].numerator;
        auto denominator1 = node_infos[i1].denominator;
        auto denominator2 = node_infos[i2].denominator;

        auto new_numerator = numerator1 * denominator2 + numerator2 * denominator1;
        auto new_denominator = denominator1 * denominator2;
        new_numerator.zero_trim();
        new_denominator.zero_trim();

        node_infos.emplace_back(i1, i2, size1 + size2, new_numerator, new_denominator);
        node_queue.emplace(node_idx);
        ++node_idx;
    }

    vector<Polynomial<Number>> residues(node_idx);
    --node_idx;

    return {node_infos[node_idx].numerator, node_infos[node_idx].denominator};
}

ll N, M;

int solve()
{
    cin >> N >> M;

    vector<Polynomial<rll>> polys(N);
    REPD(i, 0, N)
    {
        ll a;
        cin >> a;
        polys[i] = vector<rll>{rll(1), rll(-a)};
    }

    auto [numerator, denominator] = prod(polys);
    auto formal_denominator = inv(denominator, get_value_more_than_log_2_input(M + 2));
    formal_denominator.zero_trim();
    auto results = numerator * formal_denominator;
    REPD(i, 1, M + 1)
    {
        cout << results[i].val() << endl;
    }

    return 0;
}

// main function
int main()
{
    cin.tie(0);
    ios::sync_with_stdio(false);

    solve();

    // ll t;
    // cin >> t;

    // REPD(i, 0, t)
    // {
    //     solve();
    // }

    return 0;
}
0