【题解】「CF1119H」Triple
一个暴力做法就是对于每个三元组 FWT 然后按位相乘再 IFWT 回去。
发现有性质就是每个幂级数只有三个值,那么 FWT 后的数组 \(F_{k,i} = (-1)^{popcount(i\&a_k)}x+(-1)^{popcount(i\&b_k)}y+(-1)^{popcount(i\&c_k)}z\) 只有 \(2^3\) 种取值。
注意到一个三元组 \(\{a, b, c\}\) 可以转化为三元组 \(\{0, b\oplus a, c\oplus a\}\),这样只有 \(2^2\) 个值了。
那么我们可以考虑每种取值的个数,快速幂就能算出所有 FWT 数组按位相乘的结果了。
因为 \(a_k = 0\) 所以 \(x\) 前的系数一定是正数。
设有 \(c_1\) 个 \({x+y+z}\),\(c_2\) 个 \({x+y-z}\),\(c_3\) 个 \({x-y+z}\),\(c_4\) 个 \({x-y-z}\)。
下面的问题就是思考怎么得到 \(c\)。
首先有 \(c_1 + c_2 + c_3 + c_4 = n\)。
设 \(x = 0, y = 1, z = 0\),此时 FWT 数组就是 \(F_{k, i} = (-1)^{popcount(i\&b_k)}\),得到 \(c_1 + c_2 - c_3 - c_4 = p_1\)。
同理令 \(x = 0, y = 0, z = 1\),得到 \(c_1 - c_2 + c_3 - c_4 = p_2\)。
注意到如果我们再令 \(x=1, y=0, z=0\) 的话方程与第一个方程相同。
根据 FWT 的性质,如果我们让幂级数的 \(b_k\oplus c_k\) 位为 \(1\),那么 \(F_{k, i} = (-1)^{popcount(i\&b_k)}(-1)^{popcount(i\&c_k)}\),得到 \(c_1 - c_2 - c_3 + c_4 = p_3\)。
这样我们就是四个变量,四个未知数,可以直接解方程。得到:\(c_1 = \frac{n + p_1 + p_2 + p_3}4, c_2 = \frac{n+p_1}2-c_1, c_3 = \frac{n+p_2}2-c_1, c_4=\frac{n+p_3}2-c_1\)。
Code
#include <bits/stdc++.h>
#define FOR(i,j,k) for(int i=j; i<=k; ++i)
#define ROF(i,j,k) for(int i=j; i>=k; --i)
inline int read (void) {
int x = 0, f = 1, ch = getchar();
while(!isdigit(ch)) { if(ch == '-') f = -f; ch = getchar(); }
while(isdigit(ch)) { x = x * 10 + ch - '0'; ch = getchar(); }
return x * f;
}
using ll = long long;
const int mod = 998244353;
inline int ksm (int a, int b) {
int c = 1;
while(b) {
if(b&1) c = 1ll * c * a % mod;
a = 1ll * a * a % mod; b >>= 1;
} return c;
}
const int inv2 = ksm (2, mod-2);
const int inv4 = ksm (4, mod-2);
inline void fwt (int *a, int lim, bool f=0) {
int t = f ? inv2 : 1, x, y;
FOR(i,1,lim) for(int j=0; j<1<<lim; j+=1<<i) FOR(k,0,(1<<i-1)-1) {
x = ((ll) a[j|k] + a[1<<i-1|j|k]) * t % mod;
y = ((ll) a[j|k] + mod - a[1<<i-1|j|k]) * t % mod;
a[j|k] = x, a[1<<i-1|j|k] = y;
}
}
int f[4][1<<17];
int main (void) {
int n = read(), k = read(), x = read(), y = read(), z = read(), xor_a = 0;
FOR(i,1,n) {
int a = read(), b = read(), c = read();
xor_a ^= a; b ^= a; c ^= a;
++ f[0][b]; ++ f[1][c]; ++ f[2][b^c];
}
fwt (f[0], k); fwt (f[1], k); fwt (f[2], k);
int a = ((ll) x + y + z) % mod, b = ((ll) x + y - z + mod) % mod, c = ((ll) x - y + z + mod) % mod, d = ((ll) x - y - z + 2 * mod) % mod;
FOR(i,0,(1<<k)-1) {
int c1 = ((ll) n + f[0][i] + f[1][i] + f[2][i]) * inv4 % mod, c2 = (((ll) n + f[0][i]) * inv2 + mod - c1) % mod, c3 = (((ll) n + f[1][i]) * inv2 + mod - c1) % mod, c4 = (((ll) n + f[2][i]) * inv2 + mod - c1) % mod;
f[3][i] = (ll) ksm (a, c1) * ksm (b, c2) % mod * ksm (c, c3) % mod * ksm (d, c4) % mod;
}
fwt (f[3], k, 1);
FOR(i,0,(1<<k)-1) printf("%d%c", f[3][i^xor_a], i==(1<<k)-1?10:32);
return 0;
}

浙公网安备 33010602011771号