FWT,FST入门

0.目录

目录

  • 0.目录
  • 1.什么是 FWT
  • 2. FWT 怎么做
    • 2.1. 或卷积
    • 2.2.与卷积
    • 2.3.异或卷积
    • 2.4.例题
  • 3. FST
    • 3.1. FST 怎么做
    • 3.2.例题

1.什么是 FWT

?? FWT 全称为 " 快速沃尔什变换: Fast Walsh Transform " 。可以用于解决位运算卷积的问题。

??什么叫位运算卷积呢?我们考虑普通的卷积,即:

\[C_k=\sum_{i+j=k}A_iB_j
\]

??位运算卷积就是下标为位运算的卷积(此处与和或用 C++ 记号,异或用\(\oplus\)):

\[\begin{aligned}\text{与卷积:}&C_k=\sum_{i\&j=k}A_iB_j\\\text{或卷积:}&C_k=\sum_{i|j=k}A_iB_j\\\text{异或卷积:}&C_k=\sum_{i\oplus j=k}A_iB_j\end{aligned}
\]

2. FWT 怎么做

??为了方便,以下我们假设所有向量长度都相等,为\(2\)的整幂,即长度\(n=2^m\)。高位以 0 补齐。

??设一个向量\(A\)经过 FWT 之后得到了\(FWT(A)\), FWT 的最终目标就是满足:\(FWT(C)=FWT(A)\cdot FWT(B)\),其中的点乘表示向量的每一位相乘:\(A\cdot B=(A_0B_0,A_1B_1,...,A_iB_i,...)\)。

?? FWT 针对三种位运算有各自的处理方法:

2.1. 或卷积

??我们发现或运算存在如下的性质:

\[(j|i=i)\land (k|i=i)\Rightarrow (j|k)|i=i
\]

??如果将二进制理解为一个 01 集合,我们就可以用集合并的方式理解上面的性质。发现这其实是一个伪分配律。

??根据这个性质我们可以进行构造:

\[a_i=\sum_{j|i=i}A_j\\b_i=\sum_{j|i=i}B_j\\c_i=\sum_{j|i=i}C_j
\]

??那么可以发现:

\[\begin{aligned}
a_ib_i
&=\sum_{j|i=i}A_j\times \sum_{k|i=i}B_k\ &=\sum_{j|i=i}\sum_{k|i=i}A_jB_k\ &=\sum_{(j|k)|i=i}A_jB_k\ &=c_i
\end{aligned}
\]

??这样做了对应乘法之后就可以得到\(c\),再进行一次逆变换就可以得到\(C\)。

??因此问题变成了怎么进行这样的变换。

??考虑一种分治(或者称为 DP )的做法:

??\(f(i,j)\):满足仅有低\(i\)位可能与\(j\)不同的,且与\(j\)或后得到\(j\)的下标所对应的数的和。

??或者可以被描述为:

\[f(i,j)=\sum_{\lfloor\frac k{2^i}\rfloor=\lfloor\frac j{2^i}\rfloor,k|j=j} a_k
\]

??考虑如何进行转移,即从\(f(i-1)\)转移到\(f(i)\)。这种情况下只有第\(i\)位解除了限制。根据或的性质,如果第\(i\)位为 0 ,那么第\(i\)位或操作之后仍需要是 0 ,就只能从第\(i\)位为 0 的\(f(i,j)\)转移来;如果第\(i\)位为 1 ,那么第\(i\)位或操作总得到是 1 ,就可以不考虑第\(i\)位,从\(f(i,j)\)和\(f(i,j+2^i)\)转移来。

??放个图片理解一下:

??顺便可以得到转移为:

??正变换:

\[\begin{aligned}
f(i,j)&=f(i-1,j)\ f(i,j+2^i)&=f(i-1,j)+f(i-1,j+2^i)
\end{aligned}
\]

??逆变换就是将特殊贡献扣除:

\[\begin{aligned}
f(i,j)&=f(i+1,j)\ f(i,j+2^i)&=f(i+1,j+2^i)-f(i+1,j)
\end{aligned}
\]

??可以发现\(f(0,i)=A_i\),且这个转移可以滚动数组优化。

??这样的 FWT 就是\(O(n\log_2n)\)。

2.2.与卷积

??与卷积与或卷积十分相似,因此可以用类似的方法分析。这里只给出状态和转移:

\[f(i,j)=\sum_{\lfloor\frac k{2^i}\rfloor=\lfloor\frac j{2^i}\rfloor,k\&j=j} a_k
\]

??正变换:

\[\begin{aligned}
f(i,j)&=f(i-1,j)+f(i-1,j+2^i)\ f(i,j+2^i)&=f(i-1,j+2^i)
\end{aligned}
\]

??逆变换:

\[\begin{aligned}
f(i,j)&=f(i+1,j)-f(i+1,j+2^i)\ f(i,j+2^i)&=f(i+1,j+2^i)
\end{aligned}
\]

2.3.异或卷积

??我们同样考虑异或的性质。

??设\(count(i)\)为\(i\)的二进制中\(1\)的位数,\(i\otimes j=count(i\&j)\bmod 2\)则异或有性质:

\[(i\otimes j)\oplus(i\otimes k)=i\otimes (j\oplus k)
\]

??即奇偶性相等。设\(count(j\&i)=a,count(k\&i)=b,count(j\&k)=c\),则左侧奇偶性由\(a+b\)决定,右侧奇偶性由\(a+b-2c\)决定,可以发现两侧的奇偶性相等。

??说起奇偶性,我们可以想到\(-1\)的幂。于是设:

\[\begin{aligned}
a_i=\sum_j(-1)^{i\otimes j}A_j\ b_i=\sum_j(-1)^{i\otimes j}B_j\ c_i=\sum_j(-1)^{i\otimes j}C_j
\end{aligned}
\]

??然后就可以看看这样转换后乘起来的结果:

\[\begin{aligned}
a_ib_i
&=\sum_j(-1)^{i\otimes j}A_j\times \sum_k(-1)^{i\otimes k}B_k\ &=\sum_{i\otimes j=0}\sum_{i\otimes k=0}A_jB_k-\sum_{i\otimes j=1}\sum_{i\otimes k=0}A_jB_k-\sum_{i\otimes j=0}\sum_{i\otimes k=1}A_jB_k+\sum_{i\otimes j=1}\sum_{i\otimes k=1}A_jB_k\ &=\sum_{i\otimes (j\oplus k)=0}A_jB_k-\sum_{i\otimes (j\oplus k)=1}A_jB_k\\
&=\sum_p(-1)^{i\otimes p}\sum_{j\oplus k=p}A_jB_k\ &=\sum_p(-1)^{i\otimes p}C_p\ &=c_i
\end{aligned}
\]

??我们达成了目的。接下来就看看怎么变换。继续考虑 DP :

\[f(i,j)=\sum_{\lfloor\frac k {2^i}\rfloor=\lfloor \frac j {2^i}\rfloor}(-1)^{j\otimes k}a_k
\]

??可以发现,从\(f(i-1)\)转到\(f(i)\)的时候,只有第\(i\)位都是\(1\)才会令\(j\otimes k\)改变奇偶性,即多乘上一个 -1 。

??这样转移,最终\(j\otimes k=0\)的情况就会被乘上偶数次 -1 ,而\(j\otimes k=1\)的情况就会被乘上奇数次 -1 ,最终答案就是正确的。

??按照这样,正变换:

\[\begin{aligned}
f(i,j)&=f(i-1,j)+f(i-1,j+2^i)\ f(i,j+2^i)&=f(i-1,j)-f(i-1,j+2^i)
\end{aligned}
\]

??逆变换,用到了小学奥数的 " 和差问题 " 的结论:

\[\begin{aligned}
f(i,j)&=\frac{f(i+1,j)+f(i+1,j+2^i)} 2\ f(i,j+2^i)&=\frac{f(i+1,j)-f(i+1,j+2^i)} 2
\end{aligned}
\]

??需要注意的是,异或卷积的逆变换还有一个 " 类 FFT " 的写法,即逆变换只比正变换在最后多除一个\(n\)(事实上异或 FWT 和 FFT 有很多相似处,可以在 K 进制 FWT 中找到答案)。

2.4.例题

??洛谷P4717。三种 FWT 全家桶。

??参考代码:

const int mod = 998244353, inv2 = 499122177;
const int MAXSIZ = 5e5 + 5;

int A[MAXSIZ], B[MAXSIZ], C[MAXSIZ], a[MAXSIZ], b[MAXSIZ];
int N, M;

int fix( const int x ) { return ( x % mod + mod ) % mod; }

namespace OR
{
	void FWT( int *f, const int m )
	{
		for( int s = 2 ; s <= M ; s <<= 1 )
			for( int i = 0, t = s >> 1 ; i < M ; i += s )
				for( int j = i ; j < i + t ; j ++ )
					f[j + t] = fix( f[j + t] + f[j] * m ) % mod;
	}
}

namespace AND
{
	void FWT( int *f, const int m )
	{
		for( int s = 2 ; s <= M ; s <<= 1 )
			for( int i = 0, t = s >> 1 ; i < M ; i += s )
				for( int j = i ; j < i + t ; j ++ )
					f[j] = fix( f[j] + f[j + t] * m ) % mod;
	}
}

namespace XOR
{
	void FWT( int *f, const int m )
	{
		int t1, t2;
		for( int s = 2 ; s <= M ; s <<= 1 )
			for( int i = 0, t = s >> 1 ; i < M ; i += s )
				for( int j = i ; j < i + t ; j ++ )
				{
					t1 = f[j], t2 = f[j + t];
					if( m > 0 )
						f[j] = ( t1 + t2 ) % mod,
						f[j + t] = fix( t1 - t2 );
					else
						f[j] = 1ll * ( t1 + t2 ) % mod * inv2 % mod,
						f[j + t] = 1ll * fix( t1 - t2 ) * inv2 % mod;
				}
	}
}

void cal( void ( *fwt ) ( int*, int ) )  //函数指针的写法,主要是方便。
{
	for( int i = 0 ; i < M ; i ++ ) A[i] = a[i], B[i] = b[i];
	fwt( A, 1 ), fwt( B, 1 );
	for( int i = 0 ; i < M ; i ++ ) C[i] = 1ll * A[i] * B[i] % mod;
	fwt( C, -1 );
	for( int i = 0 ; i < M ; i ++ ) write( C[i] ), putchar( i == M - 1 ? ‘\n‘ : ‘ ‘ );
}

3. FST

3.1. FST 怎么做

??它听着不妙。

??快速子集变换 FST 解决的是一类子集卷积的问题,即:

\[f(U)=\sum_{S,T\subseteq U, S\cup T=U, S\cap T=\varnothing} g(S)\times h(T)
\]

??这个卷积和或卷积的区别在于,或卷积可以有交集(并不要求\(j\& k=0\)),然而子集卷积不可以有。

??注意到这个限制在子集卷积中等价于\(|S|+|T|=|U|\)。因此我们可以给状态加上一维限制大小:

??\(f(i,U)\):大小为\(i\)的集合\(U\)的所有子集的贡献,\(g\)和\(h\)同理转换。

??这个信息可以直接用 FWT 正变换得到。

??因此有转移:

\[f(i,U)=\sum_j^i\sum_{S\cup T=U}g(i,S)\times h(i-j,T)
\]

??转移完成后需要 FWT 逆变换回来,再将不符合要求(集合大小不匹配)的清除。

3.2.例题

??[CF914G]Sum The Fibonacci, FWT + FST ,附赠题解一篇

原文地址:https://www.cnblogs.com/crashed/p/12595954.html

时间: 2024-10-09 20:46:50

FWT,FST入门的相关文章

FWT 入门

#include <bits/stdc++.h> using namespace std; #define ll long long const ll maxn = 3e5+5; const ll mod = 1e9+7; ll n; ll a[maxn], b[maxn]; void fwt(ll *a) { for(ll d=1;d<n;d<<=1) for(ll m=d<<1,i=0;i<n;i+=m) for(ll j=0;j<d;j++) {

HDU 1231 最大连续子序列 --- 入门DP

HDU 1231 题目大意以及解题思路见: HDU 1003题解,此题和HDU 1003只是记录的信息不同,处理完全相同. /* HDU 1231 最大连续子序列 --- 入门DP */ #include <cstdio> #include <cstring> int dp[10005]; int main() { #ifdef _LOCAL freopen("D:\\input.txt", "r", stdin); #endif int n

FWT 等总结

目录 与卷积: 代码: 或卷积: 代码: 异或卷积: 代码: FWT可以解决位运算卷积问题. 即\(h(i)=\sum\limits_{j⊕k=i} f(j)*g(k)\),其中"⊕"表示位运算. 与卷积: 定义\(f\)到\(F\)的变换:\(F(i)=\sum\limits_{j\&i==i}^{ }f(j)\). 这样,若\(h(i)=\sum\limits_{j and k=i} f(j)*g(k)\),则\(H(i)=F(i)*G(i)\). 变换方法:就是按照长度为

R语言快速上手入门

R语言快速上手入门 课程学习网址:http://www.xuetuwuyou.com/course/196 课程出自学途无忧网:http://www.xuetuwuyou.com 课程简介 本教程深入浅出地讲解如何使用R语言玩转数据.课程中涵盖R语言编程的方方面面,内容涉及R对象的类型.R的记号体系和环境系统.自定义函数.if else语句.for循环.S3类R的包系统以及调试工具等.本课程还通过示例演示如何进行向量化编程,从而对代码进行提速并尽可能地发挥R的潜能.本课程适合立志成为数据科学家的

笔记:Spring Cloud Zuul 快速入门

Spring Cloud Zuul 实现了路由规则与实例的维护问题,通过 Spring Cloud Eureka 进行整合,将自身注册为 Eureka 服务治理下的应用,同时从 Eureka 中获取了所有其他微服务的实例信息,这样的设计非常巧妙的将服务治理体系中维护的实例信息利用起来,使得维护服务实例的工作交给了服务治理框架自动完成,而对路由规则的维护,默认会将通过以服务名作为 ContextPath 的方式来创建路由映射,也可以做一些特别的配置,对于签名校验.登录校验等在微服务架构中的冗余问题

linux入门基础知识及简单命令介绍

linux入门基础知识介绍 1.计算机硬件组成介绍 计算机主要由cpu(运算器.控制器),内存,I/O,外部存储等构成. cpu主要是用来对二进制数据进行运算操作,它从内存中取出数据,然后进行相应的运算操作.不能从硬盘中直接取数据. 内存从外部存储中取出数据供cpu运存.内存的最小单位是字节(byte) 备注:由于32的cpu逻辑寻址能力最大为32内存单元.因此32位cpu可以访问的最大内存空间为:4GB,算法如下: 2^32=2^10*2^10*2^10*2^2 =1024*1024*1024

JAVA通信系列二:mina入门总结

一.学习资料 Mina入门实例(一) http://www.cnblogs.com/juepei/p/3939119.html Mina入门教程(二)----Spring4 集成Mina http://www.cnblogs.com/juepei/p/3940396.html Apache Mina 入门实例--创建一个MINA时间服务http://loftor.com/archives/apache-mina-quick-start-guide.html MINA2.0用户手册中文版--系列文

Storm入门(四)WordCount示例

Storm API文档网址如下: http://storm.apache.org/releases/current/javadocs/index.html 一.关联代码 使用maven,代码如下. pom.xml  和Storm入门(三)HelloWorld示例相同 RandomSentenceSpout.java /** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor lice

浅谈Ubuntu PowerShell——小白入门教程

早在去年八月份PowerShell就开始开源跨平台了,但是一直没有去尝试,叫做PowerShell Core. 这里打算简单介绍一下如何安装和简单使用,为还不知道PowerShell Core on Ubuntu的同学们提供一点小小的入门帮助,谢谢大家支持~ PowerShell Core是由Microsoft开发的运行在.Net Core上的开源跨平台的任务自动化和配置管理系统. 1.   在Ubuntu 16.04上安装PowerShell Core a)         导入公共存储库GP