XOR, AND and OR convolutions on arrays of size all follow the same recipe as FFT: transform, multiply pointwise, inverse transform, in . Subset (disjoint-union) convolution is in SOS DP.

The three transforms

All three are in-place butterflies on pairs :

ConvolutionForwardInverse
XORsame, then divide by
OR
AND
template<class T> void fwht(vector<T>& a, bool inv, int type) {   // type: 0 xor, 1 or, 2 and
    int N = a.size();
    for (int len = 1; len < N; len <<= 1)
        for (int i = 0; i < N; i += 2 * len)
            for (int j = i; j < i + len; j++) {
                T u = a[j], v = a[j + len];
                if (type == 0) a[j] = u + v, a[j + len] = u - v;
                else if (type == 1) a[j + len] = inv ? v - u : v + u;
                else a[j] = inv ? u - v : u + v;
            }
    if (type == 0 && inv) { T k = T(1) / T(N); for (auto& x : a) x *= k; }   // modular: multiply by inverse of N
}
// c = a (*) b: fwht(a,0,t); fwht(b,0,t); c[i] = a[i]*b[i]; fwht(c,1,t);

OR and AND are the subset and superset zeta/Möbius transforms. XOR is the Walsh-Hadamard transform — the direct analogue of FFT over instead of complex roots of unity. Its coefficients are exactly the Fourier spectrum of a Boolean function over (the basis of Boolean function analysis and Reed-Muller code decoding), beyond CP but worth knowing where the name comes from:

Using the transform structure

The transform of a single “indicator” is everywhere: . So products of many sparse factors can be computed in the transform domain without convolving them one by one.

Count subsets with XOR , or choose one element from each of groups: for “pick any subset of ”, the product is . In the transform domain each factor is . So if every has even overlap with , else 0. (The rank of an XOR basis gives the same answer: subsets per reachable value.)

Product of factors where each transform takes only two values or : for each , count how many factors take the “minus” value. Let be that count; then over the “plus” factors times the “minus” factors. Counting for all needs one more transform of the sum of the indicators: . This is the classic trick for “each of triples, choose one value, count XOR outcomes” in (CF 1119H “Triple”): with three values per group, solve a small linear system for the number of groups in each sign pattern.

Repeated self-convolution: is pointwise , so “XOR of independent choices” costs one transform plus fast powers.

Rank and linear algebra: the support of the transform of the indicator of a linear subspace is its orthogonal complement . That links XOR transforms to XOR bases (XOR Basis).

Variants

  • Modular arithmetic: the XOR inverse divides by ; multiply by its modular inverse (needs an odd modulus).
  • Floating point: fine for probabilities. Use double and divide by at the end.
  • Base- “XOR” (digit-wise addition mod ): use the -point DFT on each digit (roots of unity mod when , or an extension ring). For the transform uses with .
  • Max-plus “OR convolution” (): no fast transform in general. If is monotone, zeta with max then split as needed; otherwise subset enumeration in .
  • GCD and LCM convolutions on : the same idea on the divisor lattice. “Sum over multiples” (zeta) and Möbius over divisors give in with a prime-by-prime sweep (Möbius).

Uses

ProblemConvolution
number of pairs with for every XOR self-convolution of frequencies
Nim: probability the XOR of random piles is 0XOR power of the pile distribution
count pairs with OR convolution
expected value of AND of random picksAND convolution
”choose one of three values in each group, count XOR results”transform-domain counting (above)
game sums: distribution of Grundy XORXOR convolution