firiexp's Library

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub firiexp/library

:heavy_check_mark: OR畳み込み(Bitwise OR Convolution)
(math/or_convolution.cpp)

説明

bitwise OR 畳み込みを計算する。 c[S] = Σ_{A | B = S} a[A] b[B] を返す。 計算量は $O(N log N)$。

できること

使い方

T には +, -, *, +=, -=, *= が必要。 OR 畳み込み以外にも subset zeta / mobius transform を単体で使える。

Verified with

Code

template<class T>
void subset_zeta_transform(vector<T> &v){
    int n = 1;
    while (n < (int)v.size()) n <<= 1;
    v.resize(n);
    for (int i = 1; i < n; i <<= 1) {
        for (int s = 0; s < n; ++s) {
            if ((s & i) == 0) v[s | i] += v[s];
        }
    }
}

template<class T>
void subset_mobius_transform(vector<T> &v){
    int n = 1;
    while (n < (int)v.size()) n <<= 1;
    v.resize(n);
    for (int i = 1; i < n; i <<= 1) {
        for (int s = 0; s < n; ++s) {
            if ((s & i) == 0) v[s | i] -= v[s];
        }
    }
}

template<class T>
vector<T> or_convolution(vector<T> a, vector<T> b){
    int n = 1;
    while (n < (int)a.size() || n < (int)b.size()) n <<= 1;
    a.resize(n);
    b.resize(n);
    subset_zeta_transform(a);
    subset_zeta_transform(b);
    for (int i = 0; i < n; ++i) a[i] *= b[i];
    subset_mobius_transform(a);
    return a;
}

/**
 * @brief OR畳み込み(Bitwise OR Convolution)
 */
#line 1 "math/or_convolution.cpp"
template<class T>
void subset_zeta_transform(vector<T> &v){
    int n = 1;
    while (n < (int)v.size()) n <<= 1;
    v.resize(n);
    for (int i = 1; i < n; i <<= 1) {
        for (int s = 0; s < n; ++s) {
            if ((s & i) == 0) v[s | i] += v[s];
        }
    }
}

template<class T>
void subset_mobius_transform(vector<T> &v){
    int n = 1;
    while (n < (int)v.size()) n <<= 1;
    v.resize(n);
    for (int i = 1; i < n; i <<= 1) {
        for (int s = 0; s < n; ++s) {
            if ((s & i) == 0) v[s | i] -= v[s];
        }
    }
}

template<class T>
vector<T> or_convolution(vector<T> a, vector<T> b){
    int n = 1;
    while (n < (int)a.size() || n < (int)b.size()) n <<= 1;
    a.resize(n);
    b.resize(n);
    subset_zeta_transform(a);
    subset_zeta_transform(b);
    for (int i = 0; i < n; ++i) a[i] *= b[i];
    subset_mobius_transform(a);
    return a;
}

/**
 * @brief OR畳み込み(Bitwise OR Convolution)
 */
Back to top page