0
点赞
收藏
分享

微信扫一扫

【省选模拟】西行(FWT)

【省选模拟】西行(FWT)_git

看完题立马联想到黎明前的巧克力
暴力的做法是对每一行做一遍 【省选模拟】西行(FWT)_#define_02,这样子是 【省选模拟】西行(FWT)_git_03
发现每个位置的贡献要么是 【省选模拟】西行(FWT)_i++_04 要么是 【省选模拟】西行(FWT)_git_05,那么我们可以合起来做 【省选模拟】西行(FWT)_#define_02
只需要知道这 【省选模拟】西行(FWT)_#define_07 种正负组合出现多少次就可以了
问题就是出现了多少次,考场始终觉得方程不够,结果发现自己 sb 了
黎明前的巧克力还记得一个位置要么是【省选模拟】西行(FWT)_#define_08,要么是 【省选模拟】西行(FWT)_#define_09,因为 【省选模拟】西行(FWT)_git_10 在位置 0 上
于是我们把每一行的 【省选模拟】西行(FWT)_git_11 变成 0,其它的全部异或上 【省选模拟】西行(FWT)_git_11 就可以了
假设现在有四种系数 【省选模拟】西行(FWT)_#define_13,个数为 【省选模拟】西行(FWT)_git_14
我们在 【省选模拟】西行(FWT)_git_10 的位置上 +1 做 【省选模拟】西行(FWT)_i++_16,就可以得到 【省选模拟】西行(FWT)_#define_17 的值
【省选模拟】西行(FWT)_i++_18 的位置上 +1 就可以得到 【省选模拟】西行(FWT)_git_19 的值
发挥人类智慧在 【省选模拟】西行(FWT)_i++_20 的位置 +1 就可以得到两个符号的异或,也就是这个式子:
【省选模拟】西行(FWT)_i++_21, 【省选模拟】西行(FWT)_i++_22
那么我们得到了 【省选模拟】西行(FWT)_i++_23 的值
还有一个 【省选模拟】西行(FWT)_#define_24 即可以解出,不能暴力解,巧妙的发现
【省选模拟】西行(FWT)_#define_24
【省选模拟】西行(FWT)_git_26
【省选模拟】西行(FWT)_i++_27
【省选模拟】西行(FWT)_i++_28
把得到的 【省选模拟】西行(FWT)_git_29 回去就可以得到原来的
那么复杂度就是 【省选模拟】西行(FWT)_#define_30

#include<bits/stdc++.h>
#define cs const
using namespace std;
typedef long long ll;
int read(){
ll cnt = 0, f = 1; char ch = 0;
while(!isdigit(ch)){ ch = getchar(); if(ch == '-') f = -1; }
while(isdigit(ch)) cnt = cnt*10 + (ch-'0'), ch = getchar();
return cnt * f;
}
cs int Mod = 998244353;
int add(int a, int b){ return a + b >= Mod ? a + b - Mod : a + b; }
int mul(int a, int b){ return 1ll * a * b % Mod; }
int dec(int a, int b){ return a - b < 0 ? a - b + Mod : a - b; }
int ksm(int a, int b){ int ans = 1; for(;b;b>>=1,a=mul(a,a)) if(b&1) ans = mul(ans, a); return ans; }
void Add(int &a, int b){ a = add(a, b); }
void Dec(int &a, int b){ a = dec(a, b); }
void Mul(int &a, int b){ a = mul(a, b); }
cs int N = 1e6 + 50, K = 10, M = 1 << 9;
int n, m, k, Sm, Sk, a[K], p[N][K];
#define poly vector<int>
poly vl[M];
void FWT(poly &a, int S, int typ){
for(int i = 1; i < S; i <<= 1)
for(int j = 0; j < S; j += (i<<1))
for(int k = 0; k < i; k++){
int x = a[k + j], y = a[k + j + i];
a[k + j] = add(x, y); a[k + j + i] = dec(x, y);
}
if(typ == -1)
for(int i = 0, iv = ksm(S,Mod-2); i < S; i++) Mul(a[i], iv);
}
int main(){
n = read(), m = read(), k = read();
Sm = 1 << m;
Sk = 1 << k - 1;
for(int i = 0; i < k; i++) a[i] = read();
int tag = 0;
for(int i = 1; i <= n; i++){
p[i][0] = read(); tag ^= p[i][0];
for(int j = 1; j < k; j++) p[i][j] = read(), p[i][j] ^= p[i][0];
}
for(int S = 0; S < Sk; S++){
vl[S].resize(n + 1);
vl[S][0] = 1; vl[S][1] = a[0];
for(int j = 1; j < k; j++)
(S >> (j - 1) & 1) ? Dec(vl[S][1], a[j]) : Add(vl[S][1], a[j]);
for(int j = 2; j <= n; j++) vl[S][j] = mul(vl[S][1],vl[S][j-1]);
}
static poly f[M];
for(int S = 0; S < Sk; S++){
f[S].resize(Sm);
for(int i = 1; i <= n; i++){
int x = 0;
for(int j = 1; j < k; j++) if(S >> (j - 1) & 1) x ^= p[i][j];
++f[S][x];
}
FWT(f[S], Sm, 1);
}
poly F(Sm, 1);
for(int i = 0; i < Sm; i++){
poly G(Sk, 0);
for(int j = 0; j < Sk; j++) G[j] = f[j][i];
FWT(G, Sk, -1);
for(int j = 0; j < Sk; j++) Mul(F[i], vl[j][G[j]]);
}
FWT(F, Sm, -1);
for(int i = 0; i < Sm; i++) cout << F[i ^ tag] << " ";
return 0;
}


举报

相关推荐

0 条评论