首页 > 其他分享 >FWT学习笔记

FWT学习笔记

时间:2024-02-23 22:23:01浏览次数:28  
标签:right int sum 笔记 学习 fwt FWT otimes left

FWT/快速沃尔什变换

前言

FWT是处理一类问题形如(\(\oplus\)指or,and,xor二元运算符)

\[c_{i}=\sum_{i=j \oplus k} a_{j} b_{k} \]

考虑像FFT一样,用\(O(n\log n)\)的复杂度构造出\(fwt\),在\(O(n)\)计算出\(fwt_a\times fwt_b\),最后在\(O(n\log n)\)将\(fwt\)转化回去

正题

OR

考虑构造

\[fwt_i=\sum_{j|i=i}a_j \]

那么

\[\begin{aligned} fwt[a] \times fwt[b] &= \left(\sum_{j|i=i} a_j\right)\left(\sum_{k|i=i} b_k\right) \\\\ &= \sum_{j|i=i} \sum_{k|i=i} a_jb_k \\\\ &= \sum_{(j|k)|i = i} a_jb_k \\\\ &= fwt[c] \end{aligned} \]

考虑按位计算fwt,如果新的一位是1,那么它要加上对应新的一位是0的值

然后IOR就是相当于逆运算(inv=-1)

void OR(int* f,int inv){
	for(int l=1;l<=n/2;l<<=1) for(int i=1;i<=n;i+=l<<1) Fu(j,i,i+l-1) 
		f[j+l]=(1ll*f[j+l]+f[j]*inv+mod)%mod;
}

AND

构造和证明与OR类似

\[fwt_i=\sum_{j\&i=i}a_j \]

考虑按位计算fwt,如果新的一位是0,那么它要加上对应新的一位是1的值

void AND(int* f,int inv){
	for(int l=1;l<=n/2;l<<=1) for(int i=1;i<=n;i+=l<<1) Fu(j,i,i+l-1) 
		f[j]=(1ll*f[j]+f[j+l]*inv+mod)%mod;
}

XOR

定义 \(x\otimes y=\text{popcount}(x \& y) \bmod 2\),其中 \(\text{popcount}\) 表示「二进制下 \(1\) 的个数」。

满足 \((i \otimes j) \operatorname{xor} (i \otimes k) = i \otimes (j \operatorname{xor} k)\)。

证明很好想,就是考虑1的个数mod2后xor,等价于加起来在异或,而+和xor的奇偶性不变

构造 \(fwt[a]_i = \sum_{i\otimes j = 0} a_j - \sum_{i\otimes j = 1} a_j\)。

\[\begin{aligned} fwt[a] \times fwt[b] &= \left(\sum_{i\otimes j = 0} a_j - \sum_{i\otimes j = 1} a_j\right)\left(\sum_{i\otimes k = 0} b_k - \sum_{i\otimes k = 1} b_k\right) \\ &=\left(\sum_{i\otimes j=0}a_j\right)\left(\sum_{i\otimes k=0}b_k\right)-\left(\sum_{i\otimes j=0}a_j\right)\left(\sum_{i\otimes k=1}b_k\right)-\left(\sum_{i\otimes j=1}a_j\right)\left(\sum_{i\otimes k=0}b_k\right)+\left(\sum_{i\otimes j=1}a_j\right)\left(\sum_{i\otimes k=1}b_k\right) \\ &=\sum_{i\otimes(j \operatorname{xor} k)=0}a_jb_k-\sum_{i\otimes(j\operatorname{xor} k)=1}a_jb_k \\ &= fwt[c] \end{aligned} \]

很好证明,就是分配律,然后利用上面的性质化简

还是考虑一位一位计算,新加的一位如果是0,那么不改变\(\otimes\)后的值,直接把0,1都加上

如果是1,对于0的话不变,对于1的话变成相反数

最后IXOR的inv=1/2

void XOR(int* f,int inv){
	for(int l=1;l<=n/2;l<<=1) for(int i=1;i<=n;i+=l<<1) Fu(j,i,i+l-1){
		int x=f[j],y=f[j+l];
		f[j]=1ll*inv*(x+y)%mod,f[j+l]=1ll*inv*(x-y+mod)%mod;
	}
}

K-FWT(不会证明)

我们考虑上面都是分成两部分,然后左右两半对应位置(两个位置)进行变换得到新的答案

然后我们把他考虑成矩阵乘法形式,and,or,xor分别是一下三种

\[\begin{bmatrix} 1,0\\1,1 \end{bmatrix}\\ \begin{bmatrix} 1,1\\0,1 \end{bmatrix}\\ \begin{bmatrix} 1,&1\\1,&-1 \end{bmatrix} \]

于是拓展成k维,就是全是1的下三角矩阵,上三角矩阵,和范德蒙德矩阵(如下)

\[\begin{bmatrix} 1& 1 & 1& ... & 1\\ 1& w_k^1& w_k^2& ... & w_k^{k - 1}\\ 1& w_k^2 & w_k^4& ... & w_k^{2(k - 1)}\\ ...& ...& ...& ...& ...\\ 1& w_k^{k - 1}& w_k^{2(k - 1)} & ... & w_k^{(k - 1)(k - 1)} \end{bmatrix} \]

然后考虑枚举长度是k的倍数,然后分成k部分,对应位就有k个,然后乘完矩阵再放回去

贺别人的代码:

void DWT(Cp *a) // 也叫 K 进制不进位加法卷积;K 进制 FWT
{
    static Cp t[10];
    for(int d = 1; d < M; d = d * V) // 从低维向高维做
        for(int i = 0; i < M; i += d * V)
            for(int j = 0; j < d; ++j) // 枚举向量的第 j 位
            {
                for(int k = 0; k < V; ++k) // n^2 跑 dft
                {
                    t[k] = Cp();
                    for(int p = 0; p < V; ++p)
                        t[k] = t[k] + a[i + j + p * d] * w[p * k];
                }
                for(int k = 0; k < V; ++k)
                    a[i + j + k * d] = t[k];
            }
}

时间复杂度我觉得是\(nk\log n\)

例题(3维):[P7930 [COCI2021-2022#1] Set](P7930 [COCI2021-2022#1] Set)

然后好像可以用原根代替单位根,然后就可以处理一些鬼畜的取mod

例题:P5109 归程

标签:right,int,sum,笔记,学习,fwt,FWT,otimes,left
From: https://www.cnblogs.com/zhy114514/p/18028263

相关文章

  • Edu-English-Phonetic-IPA:国际音标发音学:英语音标的学习神器,终于找到
    https://mp.weixin.qq.com/s?__biz=MzU3NTIzOTA5OA==&mid=2247493736&idx=1&sn=8ed10241adeaa148ee3053f5db94214e&chksm=fd248ebdca5307abf32a39eed20bb83818e00692a87298d3b1c2d2cb7b2d6572df0c0301fe7d&scene=27英语音标的学习神器,终于找到音标是记录语言的符号,对音标的正确......
  • 如何学习PYTHON(python和c++哪个难学)
    1.如何学习PYTHONPython是一门简单易学的编程语言,但想要真正掌握它需要花费不少时间和精力。我的建议是先从Python基础开始学习,掌握基本语法和常见数据结构,再逐步深入学习高级特性和应用场景。 在学习Python的过程中,https://www.fuligou8.com/noking/4006.html我们可以通过阅......
  • C语言学习方法
    学习C语言是许多编程初学者的首选,https://www.fuligou8.com/noking/22013.html因为它是一种强大且广泛使用的编程语言。然而,对于那些刚开始学习C语言的人来说,掌握它可能会有一定的挑战。在本文中,我将分享一些学习C语言的方法,帮助你更轻松地掌握这门编程语言。  1.基础知识的......
  • 【学习笔记】 - 基础数据结构 :Link-Cut Tree
    发现树剖代码太长了,给我恶心坏了学个代码短点的能写树剖题的数据结构吧前置知识平衡树splay树链剖分简介以及优缺点介绍Link-CutTree,也就是LCT,一般用于解决动态树问题Link-CutTree可用于实现重链剖分的绝大多数问题,复杂度为\(O(n\logn)\),看起来比树剖的\(O(n\lo......
  • python 加密 变量 (可用于深度学习模型加密)
    需求:深度学习基于pytorch,模型需要加密。查看到网上有使用cryptography加密的方法,如https://blog.csdn.net/weixin_43508499/article/details/124390983,总体思路是调用torch的save函数将模型保存为io.BytesIO,然后使用cryptography将保存为io.BytesIO的字节进行加密,解密......
  • 第7章 程序在何种环境中运行的 笔记
    硬件环境是程序运行的基础。它包括处理器、内存、硬盘、显示器等硬件设备。这些设备为程序的运行提供了基本的物理支持。例如,处理器负责执行程序的指令,内存则负责存储程序的数据。没有这些硬件设备,程序就无法运行。操作系统环境是程序运行的平台。操作系统是一种特殊的软件,它管理......
  • 第4章 控制方法 笔记
    控制方法是一种特殊的系统方法,它强调通过调节系统的行为和性能来达到预期的目标。这种方法的核心是反馈机制,即通过收集系统的输出信息,并将其与预期目标进行比较,然后根据差异来调整系统的输入,从而实现系统的稳定和优化。在阅读过程中,我深入了解了控制方法的具体步骤和技巧。这些包......
  • markdown学习
    Markdown学习二级标题三级标题四级标题字体hellowordhellowordhellowordhelloword引用选择狂神分割线图片超链接[点击跳转哔哩哔哩][https://www.bilibili.com/video/BV12J41137hu/?p=6&spm_id_from=pageDriver&vd_source=93e3a3e5b46479942c347265d2421476]......
  • 刘铁猛C#学习笔记9 表达式、语句2
    1.循环语句C#中有四种循环while循环,do-while循环,for计数循环,foreach遍历循环(1)while循环while()括号内写循环条件,一个bool类型表达式之后写一个嵌入式语句作为循环体 (2)do-while循环先执行一次,在判断循环条件,所以循环体至少会执行一次do{循环体}while(循环条件......
  • 刘铁猛C#学习笔记1 类与命名空间
    1、类概述//实验一“没有孩子牵着,气球在创建后就会飞走”/*(newForm()).Text="人类文明观察记录";//创建了一个Form类的实例,并命名其标题(newForm()).ShowDialog();//又创建了一个Form类的实例,并显示出来//最终显示的只有第二次创建的、没有标题的Form*///实验二......