CP Notebook

← all snippets

FastSubsetTransform

Transform to a basis with fast convolutions of the form c[z] = Σnolimits_z = x oplus y a[x] · b[y], where oplus is one of AND, OR, XOR. The size of a must be a power of two.

Time: O(N log N) 16 lines stress-tested

content/numerical/FastSubsetTransform.h — Lucian Bicsi, source: csacademy

void FST(vi& a, bool inv) {
	for (int n = sz(a), step = 1; step < n; step *= 2) {
		for (int i = 0; i < n; i += 2 * step) rep(j,i,i+step) {
			int &u = a[j], &v = a[j + step]; tie(u, v) =
				inv ? pii(v - u, u) : pii(v, u + v); // AND
				inv ? pii(v, u - v) : pii(u + v, u); // OR
				pii(u + v, u - v);                   // XOR
		}
	}
	if (inv) for (int& x : a) x /= sz(a); // XOR only
}
vi conv(vi a, vi b) {
	FST(a, 0); FST(b, 0);
	rep(i,0,sz(a)) a[i] *= b[i];
	FST(a, 1); return a;
}