cp-library

C++ Library for Competitive Programming

View the Project on GitHub emthrm/cp-library

:question: 高速ゼータ変換 (fast zeta transform)
(include/emthrm/math/convolution/fast_zeta_transform.hpp)

$g(S) = \sum_{S \subseteq T} f(T)$ または $g(S) = \sum_{T \subseteq S} f(T)$ を高速に求める。

時間計算量

$O(N\log{N})$

仕様

Yates’s algorithm

名前 戻り値  
template <bool ADDS_SUPERSET, typename Ring, typename BinOp = std::plus<Ring>>
std::vector<Ring> fast_zeta_transform(std::vector<Ring> a, const Ring ID = 0, const BinOp bin_op = BinOp());
$A$ に高速ゼータ変換を行ったもの ADDS_SUPERSET は上位集合に対する変換かを表す。

参考文献

Submissons

https://atcoder.jp/contests/arc100/submissions/10208329

Required by

Verified with

Code

#ifndef EMTHRM_MATH_CONVOLUTION_FAST_ZETA_TRANSFORM_HPP_
#define EMTHRM_MATH_CONVOLUTION_FAST_ZETA_TRANSFORM_HPP_

#include <bit>
#include <functional>
#include <vector>

namespace emthrm {

template <bool ADDS_SUPERSET, typename Ring, typename BinOp = std::plus<Ring>>
std::vector<Ring> fast_zeta_transform(
    std::vector<Ring> a, const Ring ID = 0, const BinOp bin_op = BinOp()) {
  const int n = std::bit_ceil(a.size());
  a.resize(n, ID);
  for (int i = 1; i < n; i <<= 1) {
    for (int s = 0; s < n; ++s) {
      if (s & i) continue;
      if constexpr (ADDS_SUPERSET) {
        a[s] = bin_op(a[s], a[s | i]);
      } else {
        a[s | i] = bin_op(a[s | i], a[s]);
      }
    }
  }
  return a;
}

}  // namespace emthrm

#endif  // EMTHRM_MATH_CONVOLUTION_FAST_ZETA_TRANSFORM_HPP_
#line 1 "include/emthrm/math/convolution/fast_zeta_transform.hpp"



#include <bit>
#include <functional>
#include <vector>

namespace emthrm {

template <bool ADDS_SUPERSET, typename Ring, typename BinOp = std::plus<Ring>>
std::vector<Ring> fast_zeta_transform(
    std::vector<Ring> a, const Ring ID = 0, const BinOp bin_op = BinOp()) {
  const int n = std::bit_ceil(a.size());
  a.resize(n, ID);
  for (int i = 1; i < n; i <<= 1) {
    for (int s = 0; s < n; ++s) {
      if (s & i) continue;
      if constexpr (ADDS_SUPERSET) {
        a[s] = bin_op(a[s], a[s | i]);
      } else {
        a[s | i] = bin_op(a[s | i], a[s]);
      }
    }
  }
  return a;
}

}  // namespace emthrm
Back to top page