This documentation is automatically generated by online-judge-tools/verification-helper
#include "convolution/and_convolution.hpp"
長さ $2^N$ の整数列 $a$ と $b$ について、 $c_k = \sum_{i\& j=k} a_i b_j$ を求める。 $O(N 2^N)$
#pragma once
#include <vector>
#include "../set_function/superset_transform.hpp"
namespace ebi {
template <class T>
std::vector<T> and_convolution(const std::vector<T> &a,
const std::vector<T> &b) {
int n = a.size();
auto ra = superset_zeta(a);
auto rb = superset_zeta(b);
for (int i = 0; i < n; i++) {
ra[i] *= rb[i];
}
return superset_mobius(ra);
}
} // namespace ebi
#line 2 "convolution/and_convolution.hpp"
#include <vector>
#line 2 "set_function/superset_transform.hpp"
#include <bit>
#include <cassert>
#line 6 "set_function/superset_transform.hpp"
namespace ebi {
template <class T> std::vector<T> superset_zeta(const std::vector<T> &a) {
int n = std::bit_width(a.size()) - 1;
assert((1 << n) == (int)a.size());
std::vector<T> ra = a;
for (int i = 0; i < n; i++) {
int w = 1 << i;
for (int p = 0; p < (1 << n); p += 2 * w) {
for (int s = p; s < p + w; s++) {
int t = s | w;
ra[s] += ra[t];
}
}
}
return ra;
}
template <class T> std::vector<T> superset_mobius(const std::vector<T> &ra) {
int n = std::bit_width(ra.size()) - 1;
assert((1 << n) == (int)ra.size());
std::vector<T> a = ra;
for (int i = 0; i < n; i++) {
int w = 1 << i;
for (int p = 0; p < (1 << n); p += 2 * w) {
for (int s = p; s < p + w; s++) {
int t = s | w;
a[s] -= a[t];
}
}
}
return a;
}
} // namespace ebi
#line 6 "convolution/and_convolution.hpp"
namespace ebi {
template <class T>
std::vector<T> and_convolution(const std::vector<T> &a,
const std::vector<T> &b) {
int n = a.size();
auto ra = superset_zeta(a);
auto rb = superset_zeta(b);
for (int i = 0; i < n; i++) {
ra[i] *= rb[i];
}
return superset_mobius(ra);
}
} // namespace ebi