CF1119H Triple
EternalAlexander · · 题解
尝试解决更为一般化的问题:给定
考虑将 黎明前的巧克力 一题的做法扩展到一般情况。
此时,一个多项式的 FWT 数组的每一项有
令
考虑对于
考虑
当
敏锐的读者此时应该已经意识到了,这正是 FWT 的系数。即,若求出
下面是我的代码实现。将
#include <bits/stdc++.h>
using ll = long long;
const int mod = 998244353;
const int inv2 = (mod + 1) / 2;
const int maxn = (1 << 20) + 12;
int n,m,k,w[maxn],z[maxn][12],F[maxn],G[maxn],W[maxn],sum[maxn],lg[maxn];
int qpow(int a,ll b) {
if (b == 0) return 1;
ll d = qpow(a,b>>1); d = d * d % mod;
if (b & 1) d = d * a % mod;
return d;
}
void DFT(int *a,int lim,int flag){
for (int i = 1; i < lim; i <<= 1)
for (int j = 0; j < lim; j += (i << 1))
for (int k = 0; k < i; ++ k) {
ll A0 = a[j+k], A1 = a[j+k+i];
a[j+k] = (A0 + A1) % mod; a[j+k+i] = (A0 - A1 + mod) % mod;
if (flag == -1) {
a[j+k] = (ll) a[j+k] * inv2 % mod;
a[j+k+i] = (ll) a[j+k+i] * inv2 % mod;
}
}
}
int main() {
scanf("%d%d%d",&n,&m,&k);
int H[(1<<k)+10][(1<<m)+10];
std::memset(H,0,sizeof(H));
for (int i = 0; i < k; ++ i) scanf("%d",&w[i]);
lg[0] = -1;
for (int i = 0; i < (1 << k); ++ i) {
if (i) lg[i] = lg[i/2] + 1;
for (int j = 0; j < k; ++ j) {
if (i & (1 << j)) W[i] = (W[i] - w[j] + mod) % mod;
else W[i] = (W[i] + w[j]) % mod;
}
}
for (int i = 1; i <= n; ++ i) {
for (int j = 0; j < k; ++ j)
scanf("%d",&z[i][j]);
H[0][0] += 1;
for (int mask = 1; mask < (1 << k); ++ mask) {
int lowbit = mask & -mask;
int b = lg[lowbit];
sum[mask] = sum[mask - lowbit] ^ z[i][b];
H[mask][sum[mask]] += 1;
}
}
for (int mask = 0; mask < (1 << k); ++ mask)
DFT(H[mask],(1<<m),1);
for (int i = 0; i < (1 << m); ++ i) {
for (int j = 0; j < (1 << k); ++ j)
G[j] = H[j][i];
DFT(G,(1<<k),-1);
F[i] = 1;
for (int j = 0; j < (1 << k); ++ j)
F[i] = (ll) F[i] * qpow(W[j],G[j]) % mod;
} DFT(F,(1<<m),-1);
for (int i = 0; i < (1 << m); ++ i)
printf("%d ",F[i]);
return 0;
}