注意到原题方案数相当于选择一个异或和为 0 的子集 S 并乘上 2∣S∣ 的系数。那么可以列出答案柿子为:
[x0]i=1∏n(1+2xai)
这可以使用类似分治 NTT 的东西来做到 O(n+m22m),具体来讲就是分别只保留最高位为 0 或 1 的部分递归下去,然后使用这两部分的结果分别合并出最后异或出来时最高位为 0 或 1 的结果。这样做时间复杂度正确的原理在于,如果设值域为 2m,且确定了长度为 k 的前缀,那么这些东西只能异或出 O(2m−k) 种结果。
但是我们也许可以做到更优。考虑求出这个东西 FWT 之后的结果,再 IFWT 回去:
[xk]FWT(i=1∏n(1+2xai))
我们直接去考虑更加一般的情况:对于每个 k,我们都需要求出:(这里的 ai 和前面的 ai 意义不同)
[xk]FWT(i=1∏n(ai+bixci))
然后我们发现,(ai+bixic)(di+eixic)=aidi+biei+(aiei+bidi)xc,这样我们可以将所有 ci 相同的东西合并到一起,那么问题变成了:
==[xk]FWT(i=0∏2m−1(ai+bixi))i=0∏2m−1[xk]FWT(ai+bixi)i=0∏2m−1(ai+bi(−1)∣k∩i∣)
我们再额外记录一个 ∏(ai−bi(−1)∣k∩i∣) 即可使用类似一般异或 FWT 的方法来互相转移,从而做到 O(n+m2m)。
这个题显然是上一个题中项数从 2 拓展为 3 的情况。发现并无法直接从上一题的做法拓展过来,于是可能需要关注一些在上一题中被我们忽略掉的性质,比如每一项内部的系数都是相同的 X,Y,Z。仍然考虑问题的一般化形式,假设我们需要对于每个 i 都求出:
==[xi]FWT(j=1∏np=1∑kwpxaj,p)j=1∏n[xi]FWT(p=1∑kwpxaj,p)j=1∏np=1∑kwp(−1)∣aj,p∩i∣
注意到乘积的每一项只有 2k 种取值,所以我们只需要关心每一种取值有多少个 j 可以取到即可。对于每个 i,令 s 为一个 k 位二进制数,设 cs 为:对于所有的 1≤p≤k,若 s 的第 p 位为 0,wp 贡献系数为 1,否则为 −1,符合这样的贡献形式的 j 的个数。
我们设 smj,s=⨁p∈saj,p,接着定义 hs=[xi]FWT(∑j=1nxsmj,s),则有:
hs=====[xi]FWT(j=1∑nxsmj,s)j=1∑n[xi]FWT(p∈s∏xaj,p)j=1∑np∈s∏[xi]FWT(xaj,p)j=1∑np∈s∏(−1)∣aj,p∩i∣t=0∑2k−1ct(−1)∣s∩t∣
对于最后一个等号是如何得到的,我们考虑一个 j,若它被归类到 ct 中,那么对于所有 p,都有 [p∈t]=[(−1)∣aj,p∩i∣=−1]。那么对于这样的 j,∏p∈s(−1)∣aj,p∩i∣ 中就会有 ∣s∩t∣ 个 −1。我们转而枚举 t 即可得到最后的结果。
可以发现 h 就是 c 做一次 FWT 的结果,我们 IFWT 回去即可。最后我们对于每个 i 都求出 ∏s=02k−1coscs,再做一遍 IFWT。
分析时间复杂度:求所有 sm 需要 O(n2k),求所有的 h 需要 O(m2k+m),求所有的 c 需要 O(k2k+m),预处理 cos 的次方需要 O(n2k),最后的 IFWT 需要 O(m2m),综上所述,总时间复杂度为 O(n2k+(k+m)2k+m)。
我们直接考虑对于所有异或和求出对应序列的方案数,忽略这个 K 次方。
这个题其实就是上一个题的 k=2 的情况(w1=1,w2=y,ai,1=0,ai,2=Ai)。若我们直接套用上一题的做法,求 sm,h,c 都不涉及到 y,于是时间复杂度不变;预处理 cos 的次方时需要记录 y 相关的完整系数,每次需要乘上一个单项式,在本来 O(n2k) 的基础上多乘了一个 M;求 ∏s=02k−1coscs 时涉及到了循环多项式的卷积,在本来 O(n2k) 的基础上多乘了两个 M;最后 IFWT 回去的时候,只涉及到了 y 相关的多项式的数乘与加减操作,所以只记录 y0 的系数即可,时间复杂度不变。综上所述,总时间复杂度为 O(nM22k+mlogK+(k+m)2k+m)(如果你闲着没事干可以线性筛预处理 xK 来去掉 log)。
但是我们可以优化。由于所有的 aj,1=0,所以 co0=co1,co2=co3,而 ∏s=02k−1coscs 就可以写成 FpGq 的形式,且我们只关心这个东西 y0 的系数,所以可以在预处理后 O(M) 计算。那么总时间复杂度变为 O(nM2k+mlogK+(k+m)2k+m),可以通过。
在这题里,我们要求的是:
==[xk]FWT⎝⎛i=1∏nj=li∑rixj⎠⎞i=1∏n[xk]FWT(j=1∑rixj−j=1∑li−1xj)i=1∏n([xk]FWT(j=1∑rixj)−[xk]FWT(j=1∑li−1xj))
我们设 f(r,i) 为 [xi]FWT(∑j=1rxj),那么我们要求的东西就变成了 ∏i=1n(f(ri,k)−f(li−1,k))。考虑这个 f(r,i) 的性质:
f(r,i+2j+1)=f(r,i)f(2k−1,i)=2k[imod2k=0]f(r,i)={f(2j−1,i)+f(r−2j,i)f(2j−1,i)−f(r−2j,i)i<2ji≥2j (0≤i<2j+1)f(r,i)=⎩⎪⎪⎪⎨⎪⎪⎪⎧r+1f(r−2j,i)2j+1−r−1−f(r−2j,i)i=00<i<2ji=2j2j<i<2j+1 (0≤i<2j+1)
如果我们从高到低按位考虑,我们可以写出计算 f(r,i) 的代码:
inline int calc(int r, int i, int p = n - 1){
if (!i) return r + 1;
if (r >> p & 1 ^ 1){
if (i >> p & 1) i ^= 1 << p;
return calc(r, i, p - 1);
}
if (i == 1 << p) return (1 << p + 1) - r - 1;
return i >> p & 1 ? -calc(r ^ 1 << p, i ^ 1 << p, p - 1) : calc(r ^ 1 << p, i, p - 1);
}
稍微进行一些观察,我们发现对于一个固定的 r,f(r,i) 的绝对值只与 i 的 lowbit 有关,而正负性是好求的,可以做到 O(1)。
inline int calc(int r, int i){if (!i) return r + 1;
int p = __builtin_ctz(i), neg = popc((r & i) >> p + 1) & 1 ? -1 : 1;
if (r >> p & 1) return neg * ((1 << p + 1) - (r & (1 << p + 1) - 1) - 1);
return neg * ((r & (1 << p) - 1) + 1);
}
考虑枚举 k 的 lowbit 为 p,即 k 的第 p 位为 1,更低位全为 0,更高位任意,将 lowbit 相同的 k 放在一起算。
枚举 p 后有 f(ri,k)=ai(−1)∣k′∩ri′∣,其中 ai 只与 ri 有关,k′=k/2p+1,ri′=ri/2p+1,f(li−1,k) 也是同理。那么我们所求的 ∏i=1n(f(ri,k)−f(li−1,k)) 就转化成了 ∏i=1n(ai(−1)∣k′∩ci∣+bi(−1)∣k′∩di∣) 的形式,而 ai,bi,ci,di 都是可以事先 O(1) 求出来的。
====i=1∏n(ai(−1)∣k′∩ci∣+bi(−1)∣k′∩di∣)i=1∏n[xk′]FWT(aixci+bixdi)[xk′]FWT(i=1∏n(aixci+bixdi))[xk′]FWT(i=1∏nxci(ai+bixci⊕di))[xk′]FWT(i=1∏n(0+1xci)(ai+bixci⊕di))
可以发现,这样转化过后就得到了一个第一题中的一般形式,只需要记得做完一遍后将次数从 k 还原回 k 即可。于是我们对每个 p 分别做一遍就好了。那么总时间复杂度为 O(∑p=1m(n+(m−p)2m−p))=O(m(n+2m))。