Loading

【题解】「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;
}
posted @ 2023-02-16 11:21  静谧时空  阅读(51)  评论(0)    收藏  举报