「解题报告」HDU6358 Innocence
其实挺简单的,但是考场上状态太差没推出来,暴力还挂了。麻了。
首先看题:发现,这不是我们异或 FWT 的题吗,下次出题记得标明出处
容易发现,我们实际上要求的就是集合幂级数 \([x^k](x^l + x^{l + 1} + \cdots + x^{r - 1} + x^r)^n\)。考虑直接手动模拟 FWT。
设 \(F(l, r) = FWT(x^l + x^{l + 1} + \cdots + x^{r - 1} + x^r)\),那么由于 FWT 是线性运算,我们直接前缀和差分就可以求出 \(F(l, r)\) 即可。我们设 \(G(r) = \sum_{i=0}^{r-1} x^i\),那么 \(F(l, r) = G(r + 1) - G(l)\)。那么我们要解决两个问题:
- \(G(r)\) 怎么计算;
- \(IFWT(F(l, r)^n)\) 怎么计算。
首先考虑第一个问题:直接写出 FWT 的式子:\(b_i = \sum (-1)^{p(i \operatorname{\&} j)} a_j\)。那么 \(G(r)\) 就是:
考虑将 \(r\) 按照二进制位拆开,这样原来的区间可以拆成若干个形如 \(\left[\left(\left\lfloor\dfrac{r}{2^i}\right\rfloor - 1\right) 2^i, \left\lfloor\dfrac{r}{2^i}\right\rfloor 2^i - 1\right]\) 的区间,对每一个区间进行考虑。
首先考虑 \(G(2^m)\),容易发现这时候相当于任意选定一个集合,\(i\) 和这个集合的交的奇偶性之和,写成式子就是:
即,当且仅当 \(i\) 为 \(2^m\) 的倍数时有值,值为 \(2^m\)。
那么考虑拆分成的区间,考虑从 \(G(2^i)\) 递推过来。发现,对于每一个 \(G(2^i)_ j\),实际上只需要再乘上一个 \((-1)^{p(\left\lfloor\frac{j \operatorname{\&} r}{2^i}\right\rfloor)}\) 即可。而由于 \(j\) 仅在 \(2^i | j\) 的地方有值,那么 \((-1)^{p(\left\lfloor\frac{j \operatorname{\&} r}{2^i}\right\rfloor)} = (-1)^{p(j \operatorname{\&} r) + \lfloor\frac{j}{2^i}\rfloor \operatorname{\&} 1}\),我们可以把 \((-1)^{p(j \operatorname{\&} r)}\) 提出来,那么剩下的部分其实就是交替 \(\pm 2^i\)。
那么我们就知道了,\(G(r)\) 就是若干个形如 \(\{2^i, 0, \cdots, 0, -2^i, 0, \cdots, 0, \cdots\}\) 的序列加起来。简单画一下,发现我们只关心 \(2^i\) 的 \(\mathrm{lowbit}\),\(r\) 在这一位以下的所有位都会造成贡献。而我们又能想到,除了最高位以外,其它的每一位 \(\lfloor\frac{j}{2^i}\rfloor\) 一定都是偶数,即一定都是正,而最高位一定是负数。所以我们可以得出,\(G(r)_ i\) 实际上等于 \(r \operatorname{\&} (\mathrm{lowbit}(i) - 1)\) 除去最高位的所有位减掉最高位,再乘上 \((-1)^{p(i \operatorname{\&} r)}\)。即:
需要注意 \(G(r)_0 = r\),因为 \(\mathrm{lowbit}(0)\) 没有定义。
现在考虑第二个问题:如何计算 \(IFWT(F(l, r))\)?
同样直接手拆式子,可以得到:
首先前面一部分如果 \(n\) 为奇数就直接给 \(k\) 异或上一个 \(r\),那么现在就只管后面一部分了。后面一部分比较恶心的就是那个 \((-1)^{j p((l \oplus r) \operatorname{\&} i)}\),考虑直接枚举 \(j\) 的奇偶性,那么那一部分就也可以提取出来了。发现后面的式子与 \(\mathrm{lowbit}(i)\) 有关,那么我们直接枚举这个 \(\mathrm{lowbit(i)}\),那么这部分相当于一个常量了。后面的东西是一个形如 \(\sum \binom{n}{i} a^i b^{n - i} [i \text{ is even/odd}]\),这个东西可以通过给 \(b\) 乘上一个 \(-1\),由 \(\frac{(a+b)^n \pm (a-b)^n}{2}\) 实现只保留奇数 / 偶数位置的值,然后后面那个东西就也可以 \(O(\log n)\) 求出来了。
然后考虑前面的东西,实际要求一个形如 \(\sum_{\mathrm{lowbit}(i) = 2^j} (-1)^{p(i \operatorname{\&} k)}\) 的东西。首先 \(\mathrm{lowbit}(i) = 2^j\) 的限制可以直接通过两边都除以 \(2^j\) 去掉,那么剩下的就是 \(2^{m - j - 1}(-1)^{\lfloor\frac{k}{2^{j}}\rfloor \operatorname{\&} 1}[\lfloor\frac{k}{2^{j+1}}\rfloor = 0]\)。推导略掉了,容易推出来。
那么把式子揉揉即可。不是很难写。总复杂度 \(O(Tq\log^2n)\)。
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 305, P = 1000000007;
int T;
int n, l, r, q;
int qpow(int a, int b) {
a = (a % P + P) % P;
int ans = 1;
while (b) {
if (b & 1) ans = 1ll * ans * a % P;
a = 1ll * a * a % P;
b >>= 1;
}
return ans;
}
const int INV2 = (P + 1) / 2;
int main() {
freopen("jerry.in", "r", stdin);
freopen("jerry.out", "w", stdout);
scanf("%d", &T);
while (T--) {
scanf("%d%d%d%d", &n, &l, &r, &q);
r++;
int m = 30;
while (q--) {
int k; scanf("%d", &k);
if (n & 1) k ^= r;
int ans = qpow(r - l, n);
for (int i = 0; i < m; i++) {
int p = (l & ((1 << i) - 1)) - (l & (1 << i)), q = (r & ((1 << i) - 1)) - (r & (1 << i));
int x = qpow((p + q) % P, n), y = qpow((q - p + P) % P, n);
int even = 1ll * (x + y) * INV2 % P, odd = 1ll * (y - x + P) * INV2 % P;
if (!(k >> (i + 1))) {
ans = (ans + 1ll * even * (1 << m - 1 - i) % P * ((k >> i & 1) ? P - 1ll : 1ll)) % P;
}
if (!((k ^ l ^ r) >> (i + 1))) {
ans = (ans + 1ll * odd * (1 << m - 1 - i) % P * (((k ^ l ^ r) >> i & 1) ? P - 1ll : 1ll)) % P;
}
}
ans = 1ll * ans * qpow((1 << m), P - 2) % P;
printf("%d\n", ans);
}
}
return 0;
}