Codeforces 题目传送门 & 洛谷题目传送门

FWT 的 immortal tea %%%

首先我们可以写出一个朴素的 \(dp\),设 \(dp_{i,j}\) 表示考虑前 \(i\) 个三元组中取数异或和为 \(j\) 的方案数,那么显然有 \(dp_{i,j}=Xdp_{i-1,j\oplus a_i}+Ydp_{i-1,j\oplus b_i}+Zdp_{i-1,j\oplus c_i}\),这样暴力复杂度是 \(n2^k\) 的,无法通过。

考虑优化,不难发现这个 \(dp\) 是一个异或卷积的形式,下记 \(\times\) 为幂级数之间的异或卷积操作,考虑幂级数 \(f_i\) 为满足 \([x^{a_i}]f_i=X,[x^{b_i}]f_i=Y,[x^{c_i}]=Z\),其余各项系数均为 \(0\) 的幂级数,那么不难发现 \(dp_{i-1}\times f_i=dp_i\) 成立,但是如果硬要 FWT 优化,把所有幂级数都搞一遍 FWTxor 然后乘起来,复杂度会高达 \(nk2^k\),反而跑不过暴力。

那么我们这个想法有没有前途呢?不难发现我们这个幂级数很特殊,只有三项有值,其余项都是 \(0\),并且这三项的值还是对于所有幂级数都相同的 \(X,Y,Z\),考虑以此为突破口。记 \(\hat{A}\) 为幂级数 \(A\) 的 FWTxor,我们不妨来对于某个 \(i\in[1,n]\),\(\hat{f_i}\) 有什么性质,显然根据 FWTxor 的求法 \([x^j]\hat{f_i}=(-1)^{|j\cap a_i|}X+(-1)^{|j\cap b_i|}Y+(-1)^{|j\cap c_i|}Z\),也就是说 \(\hat{f_i}\) 的每一项总共有 \(2^3=8\) 种可能,这样分类讨论还是有点烦,这里有一个小小的减少分类讨论的技巧,考虑记 \(S=\operatorname{xor}\limits_{i=1}^na_i\),我们令 \(b_i\leftarrow b_i\oplus a_i,c_i\leftarrow c_i\oplus a_i,a_i\leftarrow 0\),不难发现经过这个转化之后,真正的 \(ans_i=ans_{i\oplus S}\),不过这样 \(X\) 前的系数 \((-1)^{|j\cap a_i|}\) 就恒为 \(1\) 了,这样就只有 \(4\) 种情况了,列一下分别是 \(X+Y+Z,X+Y-Z,X-Y+Z,X-Y-Z\),如果我们知道这四种情况分别出现的次数就可以快速幂求出 \(\widehat{f_1\times f_2\times\cdots\times f_n}\) 前的系数了,再 IFWTxor 一遍即可求出 \(ans\),具体来说我们记 \(p_j\) 为有多少个 \(i\) 满足 \([x^j]\hat{f_i}=X+Y+Z\),也类似地定义了 \(q_i\) 为 \(X+Y-Z\) 的个数,\(r_i\) 为 \(X-Y+Z\) 的个数,\(s_i\) 为 \(X-Y-Z\) 的个数,那么 \([x^j]\widehat{f_1\times f_2\times\cdots\times f_n}=(X+Y+Z)^{p_i}\times(X+Y-Z)^{q_i}\times(X-Y+Z)^{r_i}\times(X-Y-Z)^{s_i}\)。

于是现在问题就变为怎样求 \(p_j,q_j,r_j,s_j\),首先有一个显然的方程 \(p_j+q_j+r_j+s_j=n\),因为每个 \([x^j]\hat{f_i}\) 都是这四种情况之一,不过只有这一个方程是显然不够的,考虑记 \(t_j=\sum\limits_{i=1}^n(-1)^{|j\cap b_i|}\),那么显然 \(t_j=p_j+q_j-r_j-s_j\),因为每个 \(X+Y+Z,X+Y-Z\) 都会对其产生 \(+1\) 的贡献,而每个 \(X-Y+Z,X-Y-Z\) 都会对其产生 \(-1\) 的贡献,另一方面,如果我们记 \(c1_j\) 为 \(\sum\limits_{i=1}^n[j=b_i]\),那么 \(t_j=\sum\limits_{k}c1_k(-1)^{|j\cap k|}\),这应该很好理解,然后对 FWT 稍微敏感一些的同学就能发现,这不就 \(\hat{c1}\) 吗,故我们有了第二个方程 \(p_j+q_j-r_j-s_j=\hat{c1}_j\),类似地,如果我们记 \(c2_j\) 为 \(\sum\limits_{i=1}^n[j=c_i]\),\(c3_j\) 为 \(\sum\limits_{i=1}^n[j=b_i\oplus c_i]\),那么 \(p_j-q_j+r_j-s_j=\hat{c2}_j,p_j-q_j-r_j+s_j=\hat{c3}_j\),推导过程类似,这里就不再赘述了,因此我们有:

\[\begin{cases}
p_j+q_j+r_j+s_j=n\\
p_j+q_j-r_j-s_j=\hat{c1}_j\\
p_j-q_j+r_j-s_j=\hat{c2}_j\\
p_j-q_j-r_j+s_j=\hat{c3}_j
\end{cases}
\]

四个未知数四个方程,把它解出来即可,\(\hat{c1},\hat{c2},\hat{c3}\) 显然可以在 \(k2^k\) 的时间内求出,因此总复杂度 \(n+k2^k\),可以通过此题。

const int MAXN=1<<17;
const int MOD=998244353;
const int INV2=499122177;
int n,k,x,y,z,ans[MAXN+5],c1[MAXN+5],c2[MAXN+5],c3[MAXN+5];
int qpow(int x,int e){
int ret=1;
for(;e;e>>=1,x=1ll*x*x%MOD) if(e&1) ret=1ll*ret*x%MOD;
return ret;
}
void FWTxor(int *a,int len,int type){
for(int i=2;i<=len;i<<=1)
for(int j=0;j<len;j+=i)
for(int k=0;k<(i>>1);k++){
int X=a[j+k],Y=a[(i>>1)+j+k];
if(type==1) a[j+k]=X+Y,a[(i>>1)+j+k]=X-Y;
else a[j+k]=1ll*(X+Y)*INV2%MOD,a[(i>>1)+j+k]=1ll*(X-Y+MOD)*INV2%MOD;
}
}
int main(){
scanf("%d%d",&n,&k);int xsum=0;
scanf("%d%d%d",&x,&y,&z);
for(int i=1,a,b,c;i<=n;i++){
scanf("%d%d%d",&a,&b,&c);b^=a;c^=a;xsum^=a;
c1[b]++;c2[c]++;c3[b^c]++;
}
FWTxor(c1,1<<k,1);FWTxor(c2,1<<k,1);FWTxor(c3,1<<k,1);
for(int i=0;i<(1<<k);i++){
int w1=(n+c1[i]+c2[i]+c3[i])/4;
int w2=(n+c1[i]-c2[i]-c3[i])/4;
int w3=(n-c1[i]+c2[i]-c3[i])/4;
int w4=(n-c1[i]-c2[i]+c3[i])/4;
// printf("%d %d %d\n",c1[i],c2[i],c3[i]);
// printf("%d %d %d %d\n",w1,w2,w3,w4);
ans[i]=1ll*qpow((x+y)%MOD+z,w1)*qpow(x+y-z,w2)%MOD*
qpow(x-y+z,w3)%MOD*qpow(x-y-z,w4)%MOD;
if(ans[i]<0) ans[i]+=MOD;
} FWTxor(ans,1<<k,-1);
for(int i=0;i<(1<<k);i++) printf("%d ",ans[i^xsum]);
return 0;
}

Codeforces 1119H - Triple(FWT)的更多相关文章

  1. 【CF850E】Random Elections(FWT)

    [CF850E]Random Elections(FWT) 题面 洛谷 CF 题解 看懂题就是一眼题了... 显然三个人是等价的,所以只需要考虑一个人赢了另外两个人就好了. 那么在赢另外两个人的过程中 ...

  2. 【CF662C】Binary Table(FWT)

    [CF662C]Binary Table(FWT) 题面 洛谷 CF 翻译: 有一个\(n*m\)的表格(\(n<=20,m<=10^5\)), 每个表格里面有一个\(0/1\), 每次可 ...

  3. 「WC2018」州区划分(FWT)

    「WC2018」州区划分(FWT) 我去弄了一个升级版的博客主题,比以前好看多了.感谢 @Wider 不过我有阅读模式的话不知为何 \(\text{LATEX}\) 不能用,所以我就把这个功能删掉了. ...

  4. 【HDU5909】Tree Cutting(FWT)

    [HDU5909]Tree Cutting(FWT) 题面 vjudge 题目大意: 给你一棵\(n\)个节点的树,每个节点都有一个小于\(m\)的权值 定义一棵子树的权值为所有节点的异或和,问权值为 ...

  5. 【UOJ#310】【UNR#2】黎明前的巧克力(FWT)

    [UOJ#310][UNR#2]黎明前的巧克力(FWT) 题面 UOJ 题解 把问题转化一下,变成有多少个异或和为\(0\)的集合,然后这个集合任意拆分就是答案,所以对于一个大小为\(s\)的集合,其 ...

  6. Codeforces663E Binary Table(FWT)

    题目 Source http://codeforces.com/contest/663/problem/E Description You are given a table consisting o ...

  7. CodeForces - 615D Multipliers(数论)

    http://codeforces.com/problemset/problem/615/D 题意 给出m个质因子,组成一个数n.问n的约数的乘积是多少,输出mod 1e+7的结果. 分析 从输入我们 ...

  8. 关于快速沃尔什变换(FWT)的一些个人理解

    定义 FWT是一种快速完成集合卷积运算的算法. 它可以用于求解类似 $C[i]=\sum\limits_{j⊗k=i}A[j]*B[k]$ 的问题. 其中⊗代表位运算中的|,&,^的其中一种. ...

  9. Codeforces Round #328(Div2)

    CodeForces 592A 题意:在8*8棋盘里,有黑白棋,F1选手(W棋往上-->最后至目标点:第1行)先走,F2选手(B棋往下-->最后至目标点:第8行)其次.棋子数不一定相等,F ...

随机推荐

  1. docker内服务访问宿主机服务

    目录 1. 场景 2. 解决 4. 参考 1. 场景 使用windows, wsl2 进行日常开发测试工作. 但是wsl2经常会遇到网络问题.比如今天在测试一个项目,核心功能是将postgres 的数 ...

  2. 深入浅出Java内存模型

    面试官:我记得上一次已经问过了为什么要有Java内存模型 面试官:我记得你的最终答案是:Java为了屏蔽硬件和操作系统访问内存的各种差异,提出了「Java内存模型」的规范,保证了Java程序在各种平台 ...

  3. 关于麦克风的参数介绍 - 驻极体麦克风(ECM)和硅麦(MEMS)

    1.麦克风的分类1.1.动圈式麦克风(Dynamic Micphone)原理:基本构造包含线圈.振膜.永久磁铁三部分.当声波进入麦克风,振膜受到声波的压力而产生振动,与振膜在一起的线圈则开始在磁场中移 ...

  4. 在c中使用正则表达式

    今天学习编译原理的时候,用c写一个简易的文法识别器实验遇到了一个问题:要用正则表达式去识别正则文法里面的A->ω,A->Bω, 其中ω属于T的正闭包,也就是说我们对正则文法的产生式进行抽象 ...

  5. 安装与卸载JDK8

    前言:学习Java的第一步需要先配置好JDK环境,而JDK8是目前使用最广泛的JDK版本.本文讲解了如何下载安装和卸载JDK8.以下环境为Windows10 下载JDK安装包 Oracle官网 所有J ...

  6. Django 开发------django-crontab实现服务端的定时任务

    一.需求: 想实现类似 Linux 中crontab 的功能.定时执行计划任务. 二.配置: a.安装插件: # pip3 install django-crontab b.在settings.py ...

  7. KMP算法-字符匹配

    字符匹配模式-KMP算法 j直接跳到了2的位置,因为在之前的都相同. 那么就需要求如果不等了之后,j需要回跳的位置next[j] 如果tk'与tj相等,则next [j+1]=k'+1 如果tk'与t ...

  8. java随手记 面向对象

    // 可以把两个类放在同一个文件中,但文件中只能有一个类是公共类,且公共类必须与文件同名,即xxx.java,源代码中的每个类编译成class文件 // java库中的类 // java.util.* ...

  9. 升级JDK8的坎坷之路

    为更好的适应JAVA技术的发展,使用更先进及前沿的技术.所以推出将我们现在使用的JDK1.6(1.7)及tomcat6(7)升级至JDK1.8及tomcat8,使我们的系统获得更好的性能,更好适应未来 ...

  10. MYSQL5.7下载安装图文教程

    MYSQL5.7下载安装图文教程 一. MYSQL两种安装包格式 MySQL安装文件分为两种,一种是msi格式的,一种是zip格式的.zip格式相当于绿色版,不需要安装,只需解压缩之后就可以使用了,但 ...