Skip to the content.

:heavy_check_mark: test/library-checker/SPS/ExpOfSetPowerSeries.test.cpp

Depends on

Code

#define PROBLEM "https://judge.yosupo.jp/problem/exp_of_set_power_series"
#include <bits/stdc++.h>

#include <atcoder/convolution>
#include <atcoder/modint>
using namespace atcoder;
using mint = modint998244353;
namespace atcoder {
std::ostream &operator<<(std::ostream &os, mint a) {
    os << a.val();
    return os;
}
std::istream &operator>>(std::istream &is, mint &a) {
    long long b;
    is >> b;
    a = b;
    return is;
}
} // namespace atcoder

#include "library/setpowerseries/Compose.hpp"
using SPS = SetPowerSeries<mint>;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int n;
    std::cin >> n;

    SPS b(1 << n);
    for (auto &x : b)
        std::cin >> x;

    SPS c = exp(b);
    for (auto &x : c)
        std::cout << x << " ";
    std::cout << std::endl;
}
#line 1 "test/library-checker/SPS/ExpOfSetPowerSeries.test.cpp"
#define PROBLEM "https://judge.yosupo.jp/problem/exp_of_set_power_series"
#include <bits/stdc++.h>

#include <atcoder/convolution>
#include <atcoder/modint>
using namespace atcoder;
using mint = modint998244353;
namespace atcoder {
std::ostream &operator<<(std::ostream &os, mint a) {
    os << a.val();
    return os;
}
std::istream &operator>>(std::istream &is, mint &a) {
    long long b;
    is >> b;
    a = b;
    return is;
}
} // namespace atcoder

#line 1 "library/setpowerseries/Compose.hpp"
// https://maspypy.com/%e9%9b%86%e5%90%88%e3%81%b9%e3%81%8d%e7%b4%9a%e6%95%b0%e9%96%a2%e9%80%a3-2-%e5%a4%9a%e9%a0%85%e5%bc%8f%e3%81%a8%e3%81%ae%e5%90%88%e6%88%90
#line 2 "library/bitwise/Util.hpp"
namespace bitwise{
  static int log2(int N){
    int n=__builtin_ffs(N)-1;
    assert((1<<n)==N);
    return n;
  }
  static bool in(int S,int a){ return (S>>a)&1; }
}
#line 3 "library/bitwise/Ranked.hpp"
#define REP_(i, n) for (int i = 0; i < (n); i++)
#define RREP_(i, n) for (int i = (n) - 1; i >= 0; i--)
class BitwiseRanked {
    static int popcount(int S) { return __builtin_popcount(S); }

  public:
    template <typename T>
    static std::vector<std::vector<T>> zeta(const std::vector<T> &A) {
        const int n = bitwise::log2(A.size());
        std::vector<std::vector<T>> RA(1 << n, std::vector<T>(n + 1, 0));
        REP_(S, 1 << n) RA[S][popcount(S)] = A[S];
        REP_(i, n)
        REP_(S, 1 << n)
        if (!bitwise::in(S, i))
            REP_(d, n + 1) RA[S | (1 << i)][d] += RA[S][d];
        return RA;
    }
    template <typename T>
    static std::vector<T> mobius(std::vector<std::vector<T>> RA) {
        const int n = bitwise::log2(RA.size());
        REP_(i, n)
        REP_(S, 1 << n)
        if (!bitwise::in(S, i))
            REP_(d, n + 1) RA[S | (1 << i)][d] -= RA[S][d];
        std::vector<T> A(1 << n);
        REP_(S, 1 << n) A[S] = RA[S][popcount(S)];
        return A;
    }
    template <typename T>
    static std::vector<T> convolution(const std::vector<T> &A,
                                      const std::vector<T> &B) {
        const int n = bitwise::log2(A.size());
        auto RA = zeta(A);
        auto RB = zeta(B);
        REP_(S, 1 << n) {
            auto &ra = RA[S], rb = RB[S];
            RREP_(d, n + 1) {
                ra[d] *= rb[0];
                REP_(i, d) ra[d] += ra[i] * rb[d - i];
            }
        }
        return mobius(RA);
    }
};
#undef REP_
#undef RREP_
#line 2 "library/util/Valarray.hpp"
#include <ranges>
#line 4 "library/util/Valarray.hpp"

template <typename T> struct Valarray : std::vector<T> {
    using std::vector<T>::vector; // コンストラクタ継承
    Valarray(const std::vector<T> &v) : std::vector<T>(v.begin(), v.end()) {}

  private:
    template <typename Op>
    Valarray &apply_inplace(const Valarray &other, Op op) {
        if (this->size() < other.size())
            this->resize(other.size(), T(0));

        for (auto [a, b] : std::views::zip(*this, other))
            a = op(a, b);

        return *this;
    }

  public:
    Valarray &operator+=(const Valarray &other) {
        return apply_inplace(other, std::plus<>());
    }
    Valarray &operator-=(const Valarray &other) {
        return apply_inplace(other, std::minus<>());
    }
    Valarray &operator*=(const Valarray &other) {
        return apply_inplace(other, std::multiplies<>());
    }
    Valarray &operator/=(const Valarray &other) {
        return apply_inplace(other, std::divides<>());
    }

    friend Valarray operator+(Valarray a, const Valarray &b) { return a += b; }
    friend Valarray operator-(Valarray a, const Valarray &b) { return a -= b; }
    friend Valarray operator*(Valarray a, const Valarray &b) { return a *= b; }
    friend Valarray operator/(Valarray a, const Valarray &b) { return a /= b; }

    Valarray operator-() const {
        Valarray g = *this;
        for (T &a : g)
            a = -a;
        return g;
    }
};
#line 4 "library/setpowerseries/Base.hpp"

template <typename T> struct SetPowerSeries : Valarray<T> {
    using SPS = SetPowerSeries;
    using Valarray<T>::Valarray;
    using Valarray<T>::size;
    using Valarray<T>::at;
    using value_type = T;

    SetPowerSeries(const std::vector<T> &f) : Valarray<T>(f) {}

    SPS operator-() const { return SPS(Valarray<T>::operator-()); }
    SPS operator*(const SPS &b) const {
        return SPS(BitwiseRanked::convolution<T>(*this, b));
    }
    SPS &operator*=(const SPS &b) { return (*this) = (*this) * b; }
};
#line 4 "library/setpowerseries/Compose.hpp"

template <typename SPS, typename T = typename SPS::value_type>
SPS SPS_exp_comp(const std::vector<T> &f, const SPS &a) {
    int N = a.size();
    int n = bitwise::log2(N);

    std::vector<SPS> ret(n + 1);
    for (int d = n; d >= 0; d--) {
        ret[d].resize(1 << (n - d));
        ret[d][0] = f[d];
        for (int m = 0; m < n - d; m++) {
            // ret[d] の [2^m, 2^{m+1}] を求める
            SPS pre(ret[d + 1].begin(), ret[d + 1].begin() + (1 << m));
            SPS a2(a.begin() + (1 << m), a.begin() + (1 << (m + 1)));
            pre *= a2;
            std::ranges::copy(pre, ret[d].begin() + (1 << m));
        }
    }
    return ret[0];
}

// sum_k f_k a^k
template <typename SPS, typename T = typename SPS::value_type>
SPS SPS_composition(const std::vector<T> &f, SPS a) {
    int N = a.size();
    int n = bitwise::log2(N);

    std::vector<T> c_pow(f.size() + 1, 1);
    for (int i = 1; i <= f.size(); i++)
        c_pow[i] = c_pow[i - 1] * a[0];

    std::vector<T> f2(n + 1, 0);
    for (int i = 0; i < f.size(); i++) {
        T now = f[i];
        for (int k = 0; k <= std::min(i, n); k++) {
            f2[k] += now * c_pow[i - k];
            now *= i - k;
        }
    }
    a[0] = 0;
    return SPS_exp_comp(f2, a);
}

template <typename SPS, typename T = typename SPS::value_type> SPS exp(SPS a) {
    int N = a.size();
    int n = bitwise::log2(N);

    SPS ret(N, 1);
    for (int d = n - 1; d >= 0; d--) {
        const int M = 1 << (n - d - 1);
        SPS pre(ret.begin(), ret.begin() + M);
        SPS a2(a.begin() + M, a.begin() + 2 * M);
        pre *= a2;
        std::ranges::copy(pre, ret.begin() + M);
    }
    return ret;
}

template <typename SPS, typename T = typename SPS::value_type> SPS log(SPS a) {
    int n = bitwise::log2(a.size());
    assert((1 << n) == a.size() and a[0] == 1);
    std::vector<T> lg(n + 1, 0);
    for (int k = 1; k <= n; k++)
        lg[k] = T(-1) / k;
    return SPS_composition(lg, SPS(1, 1) - a);
}
#line 22 "test/library-checker/SPS/ExpOfSetPowerSeries.test.cpp"
using SPS = SetPowerSeries<mint>;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int n;
    std::cin >> n;

    SPS b(1 << n);
    for (auto &x : b)
        std::cin >> x;

    SPS c = exp(b);
    for (auto &x : c)
        std::cout << x << " ";
    std::cout << std::endl;
}
Back to top page