This documentation is automatically generated by online-judge-tools/verification-helper
#include "convolution/subset_convolution_log.hpp"#pragma once
#include "subset_convolution_internal.hpp"
#include <cassert>
template <typename T>
std::vector<T> _subset_conv_log(const std::vector<T> &a, int to) {
std::vector<T> b(a.size());
for (int i = 1; i < (int) a.size(); ++i) {
b[i] = a[i] * T(i);
for (int j = 1; j <= std::min(to, i); ++j) {
b[i] -= a[j] * b[i - j];
}
}
for (int i = 1; i < (int) a.size(); ++i) {
b[i] /= T(i);
}
return b;
}
template <typename T>
std::vector<T> subset_convolution_log(const std::vector<T> &a) {
int n = 0;
while ((1 << n) < (int) a.size()) {
++n;
}
assert((int) a.size() == (1 << n));
assert(a[0] == T(1));
std::vector<std::vector<T>> a_ = subset_convolution_internal::setps(n, a);
for (int d = 0; d < n; ++ d) {
for (int i = 0; i < (1 << n); ++i) {
if (i & (1 << d)) {
subset_convolution_internal::add(a_[i], a_[i ^ (1 << d)], __builtin_popcount(i) - 1);
}
}
}
for (int i = 0; i < (1 << n); ++i) {
a_[i] = _subset_conv_log(a_[i], __builtin_popcount(i));
}
for (int d = 0; d < n; ++ d) {
for (int i = 0; i < (1 << n); ++i) {
if (i & (1 << d)) {
subset_convolution_internal::sub(a_[i], a_[i ^ (1 << d)], __builtin_popcount(i));
}
}
}
return subset_convolution_internal::rev_setps(n, a_);
}#line 2 "convolution/subset_convolution_log.hpp"
#line 2 "convolution/subset_convolution_internal.hpp"
#include <vector>
#include <algorithm>
namespace subset_convolution_internal {
template <typename T>
void add(std::vector<T> &a, const std::vector<T> &b, int to) {
for (int i = 0; i <= to; ++i) {
a[i] += b[i];
}
}
template <typename T>
void sub(std::vector<T> &a, const std::vector<T> &b, int from) {
for (int i = from; i < (int) a.size(); ++i) {
a[i] -= b[i];
}
}
template <typename T>
std::vector<std::vector<T>> setps(int n, const std::vector<T> &a) {
std::vector<std::vector<T>> sps(1 << n, std::vector<T>(n + 1, T(0)));
for (int i = 0; i < (1 << n); ++i) {
sps[i][__builtin_popcount(i)] = a[i];
}
return sps;
}
template <typename T>
std::vector<T> rev_setps(int n, const std::vector<std::vector<T>> &sps) {
std::vector<T> a(1 << n);
for (int i = 0; i < (1 << n); ++i) {
a[i] = sps[i][__builtin_popcount(i)];
}
return a;
}
} // namespace subset_convolution_internal
#line 4 "convolution/subset_convolution_log.hpp"
#include <cassert>
template <typename T>
std::vector<T> _subset_conv_log(const std::vector<T> &a, int to) {
std::vector<T> b(a.size());
for (int i = 1; i < (int) a.size(); ++i) {
b[i] = a[i] * T(i);
for (int j = 1; j <= std::min(to, i); ++j) {
b[i] -= a[j] * b[i - j];
}
}
for (int i = 1; i < (int) a.size(); ++i) {
b[i] /= T(i);
}
return b;
}
template <typename T>
std::vector<T> subset_convolution_log(const std::vector<T> &a) {
int n = 0;
while ((1 << n) < (int) a.size()) {
++n;
}
assert((int) a.size() == (1 << n));
assert(a[0] == T(1));
std::vector<std::vector<T>> a_ = subset_convolution_internal::setps(n, a);
for (int d = 0; d < n; ++ d) {
for (int i = 0; i < (1 << n); ++i) {
if (i & (1 << d)) {
subset_convolution_internal::add(a_[i], a_[i ^ (1 << d)], __builtin_popcount(i) - 1);
}
}
}
for (int i = 0; i < (1 << n); ++i) {
a_[i] = _subset_conv_log(a_[i], __builtin_popcount(i));
}
for (int d = 0; d < n; ++ d) {
for (int i = 0; i < (1 << n); ++i) {
if (i & (1 << d)) {
subset_convolution_internal::sub(a_[i], a_[i ^ (1 << d)], __builtin_popcount(i));
}
}
}
return subset_convolution_internal::rev_setps(n, a_);
}