花了一段时间把FWT技能给点了,姑且在这里记录下我对FWT的理解,其中大部分内容参考这个博客
首先,要知道FWT是用来处理这类问题的:
Ck=∑i⊗j=kAi∗Bj
其中异或可以换成其他位运算(&,|)
也可以叫它位运算卷积
对于其详细介绍以及如何在 nlogn 下完成可以看看这个博客,大概的过程就是把利用FWT把 A,B 转换成 A′,B′ ,然后有关系式
C′k=A′k∗B′k
,然后再把
C′
进行反变换ifwt变成
C
然后贴一份模板
typedef long long ll;
const int mod = 1e9+7;
ll mypow(ll x, ll n) {
ll ret = 1;
for (; n; n >>= 1) {
if (n & 1) ret = ret * x % mod;
x = x * x % mod;
}
return ret;
}
const ll inv2 = mypow(2, mod - 2);
void fwtXor(ll* a, int len) {
if (len == 1) return;
int h = len >> 1;
fwtXor(a, h);
fwtXor(a + h, h);
for (int i = 0; i < h; ++i) {
ll x1 = a[i];
ll x2 = a[i + h];
a[i] = (x1 + x2) % mod;
a[i + h] = (x1 - x2 + mod) % mod;
}
}
void ifwtXor(ll* a, int len) {
if (len == 1) return;
int h = len >> 1;
for (int i = 0; i < h; ++i) {
// y1=x1+x2
// y2=x1-x2
ll y1 = a[i];
ll y2 = a[i + h];
a[i] = (y1 + y2) * inv2 % mod;
a[i + h] = (y1 - y2 + mod) * inv2 % mod;
}
ifwtXor(a, h);
ifwtXor(a + h, h);
}
void fwtAnd(ll* a, int len) {
if (len == 1) return;
int h = len >> 1;
fwtAnd(a, h);
fwtAnd(a + h, h);
for (int i = 0; i < h; ++i) {
ll x1 = a[i];
ll x2 = a[i + h];
a[i] = (x1 + x2) % mod;
a[i + h] = x2;
}
}
void ifwtAnd(ll* a, int len) {
if (len == 1) return;
int h = len >> 1;
for (int i = 0; i < h; ++i) {
// y1=x1+x2
// y2=x2
ll y1 = a[i];
ll y2 = a[i + h];
a[i] = (y1 - y2 + mod) % mod;
a[i + h] = y2;
}
ifwtAnd(a, h);
ifwtAnd(a + h, h);
}
void fwtOr(ll* a, int len) {
if (len == 1) return;
int h = len >> 1;
fwtOr(a, h);
fwtOr(a + h, h);
for (int i = 0; i < h; ++i) {
ll x1 = a[i];
ll x2 = a[i + h];
a[i] = x1;
a[i + h] = (x2 + x1) % mod;
}
}
void ifwtOr(ll* a, int len) {
if (len == 1) return;
int h = len >> 1;
for (int i = 0; i < h; ++i) {
// y1=x1
// y2=x2+x1
ll y1 = a[i];
ll y2 = a[i + h];
a[i] = y1;
a[i + h] = (y2 - y1 + mod) % mod;
}
ifwtOr(a, h);
ifwtOr(a + h, h);
}
//len为2的幂
int len = 1 << 10;
void FWT(ll *a, ll *b, ll *c, int len) {
fwtXor(a, len);
fwtXor(b, len);
for (int i = 0; i < len; ++i) {
c[i] = a[i] * b[i] % mod;
}
ifwtXor(c, len);
}
道理我都懂,但是如何做题呢?
总之先做两题再说吧
Bob and Alice are playing numbers
题意:给你一个数组A ,和一个二元位运算符 op ,让你选择其中两个数 i 和j ,使得 i op j 最大
题解:纯粹的模板题,用来验算模板正确性color II
题意:求图的最小染色数,按题目要求输出答案
题解:图的最小染色数是经典的NP问题,显然可以看到这样一个规律:同一种颜色的点一定构成一个独立集。对于一个集合 s