后面的图片将会告诉:

如何推出FWT的公式tf

如何推出FWT的逆公式utf

用的是设系数,求系数的方法!

=========================================================

以一种高度思考

http://picks.logdown.com/posts/179290-fast-walsh-hadamard-transform

加和乘的定义

大小为1时的公式

https://blog.csdn.net/zhshrs/article/details/54838466

证明

https://blog.csdn.net/john123741/article/details/76576925

写成

or

tf(A)=(tf(A0),tf(A1)+tf(A0))

utf(A)=(utf(A0),utf(A1)-utf(A0))

and

tf(A)=(tf(A0)+tf(A1),tf(A1))

utf(A)=(utf(A0)-utf(A1),utf(A1))

xor

tf(A)=(tf(A0)+tf(A1),tf(A0)-tf(A1))

utf(A)=(1/2*(utf(A0)+utf(A1)),1/2*(utf(A0)-utf(A1)))

更好记忆一点

对于or,and

0 = 0 or 0 对应 or tf(A0)[utf(A0)]

1 = 1 and 1 对应 and tf(A1)[utf(A1)]

=================================

and or xor 二进制操作

0~2^(k-1)-1时,最高位为0

2^(k-1)~2^k-1时,最高位为1

e.g.

000

001

010

011

----

100

101

110

111

P.S.:

FFT和FWT,两者虽然实现方法都是内容分半(二分),但是其本质原理不同。

FFT: http://www.cnblogs.com/zwfymqz/p/8244902.html

快速莫比乌斯变换

study from :

https://yhx-12243.github.io/OI-transit/records/vijos%20%234.html

适用于and or,xor 行不通

FMT写法和FWT是一样的,两者考虑问题角度不一样。

https://www.luogu.org/problemnew/show/P4717

存储函数地址

void (*addr1[3])(ll a[])={fwt1,fwt2,fwt3};
    void (*addr2[3])(ll a[])={ufwt1,ufwt2,ufwt3};

also can use (int type)=1ll*...

注意当数字范围为[0,x]

遍历范围 [0,z) tot=2*x(大于any i op j, 其中i,j in [0,x])

而数组开z大小

对于代码中的tot,要写成2^k的形式,

否则如写成tot,e.g. tot=9,  8(i)+3(j)>9。

对应好记忆

 #include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
using namespace std;
#define ll long long const double eps=1e-;
const ll inf=1e9;
const ll mod=;
const int maxn=(<<)*; ///any n or <2n /**
补全为2^k
**/ ll aa[maxn],bb[maxn],a[maxn],b[maxn];
int tot;
ll mod_inv_2=(mod+)/; ///or
void fwt1(ll *a)
{
int cnt_pre,cnt_cur,i,j;
for (cnt_pre=,cnt_cur=;cnt_pre<tot;cnt_pre<<=,cnt_cur<<=)
for (i=;i<tot;i+=cnt_cur)
for (j=;j<cnt_pre;j++)
(a[i+j+cnt_pre]+=a[i+j])%=mod;
} void ufwt1(ll *a)
{
int cnt_pre,cnt_cur,i,j;
for (cnt_pre=tot>>,cnt_cur=tot;cnt_pre>;cnt_pre>>=,cnt_cur>>=)
// for (cnt_pre=1,cnt_cur=2;cnt_pre<tot;cnt_pre<<=1,cnt_cur<<=1)
for (i=;i<tot;i+=cnt_cur)
for (j=;j<cnt_pre;j++)
(a[i+j+cnt_pre]-=a[i+j]-mod)%=mod;
} ///and
void fwt2(ll *a)
{
int cnt_pre,cnt_cur,i,j;
for (cnt_pre=,cnt_cur=;cnt_pre<tot;cnt_pre<<=,cnt_cur<<=)
for (i=;i<tot;i+=cnt_cur)
for (j=;j<cnt_pre;j++)
(a[i+j]+=a[i+j+cnt_pre])%=mod;
} void ufwt2(ll *a)
{
int cnt_pre,cnt_cur,i,j;
for (cnt_pre=tot>>,cnt_cur=tot;cnt_pre>;cnt_pre>>=,cnt_cur>>=)
// for (cnt_pre=1,cnt_cur=2;cnt_pre<tot;cnt_pre<<=1,cnt_cur<<=1)
for (i=;i<tot;i+=cnt_cur)
for (j=;j<cnt_pre;j++)
(a[i+j]-=a[i+j+cnt_pre]-mod)%=mod;
} ///xor
void fwt3(ll *a)
{
int cnt_pre,cnt_cur,i,j;
ll x;
for (cnt_pre=,cnt_cur=;cnt_pre<tot;cnt_pre<<=,cnt_cur<<=)
for (i=;i<tot;i+=cnt_cur)
for (j=;j<cnt_pre;j++)
{
x=a[i+j];
a[i+j]=(a[i+j]+a[i+j+cnt_pre])%mod;
a[i+j+cnt_pre]=(x-a[i+j+cnt_pre]+mod)%mod;
}
} void ufwt3(ll *a)
{
int cnt_pre,cnt_cur,i,j;
ll x;
for (cnt_pre=tot>>,cnt_cur=tot;cnt_pre>;cnt_pre>>=,cnt_cur>>=)
// for (cnt_pre=1,cnt_cur=2;cnt_pre<tot;cnt_pre<<=1,cnt_cur<<=1)
for (i=;i<tot;i+=cnt_cur)
for (j=;j<cnt_pre;j++)
{
x=a[i+j];
a[i+j]=(a[i+j]+a[i+j+cnt_pre])*mod_inv_2%mod;
a[i+j+cnt_pre]=(x-a[i+j+cnt_pre]+mod)*mod_inv_2%mod; ///x-
}
} int main()
{
int n,i,j;
scanf("%d",&n);
tot=<<n;
for (i=;i<tot;i++)
scanf("%lld",&aa[i]);
for (i=;i<tot;i++)
scanf("%lld",&bb[i]); void (*addr1[]) (ll a[])={fwt1,fwt2,fwt3};
void (*addr2[]) (ll a[])={ufwt1,ufwt2,ufwt3}; for (i=;i<;i++)
{
memcpy(a,aa,sizeof(aa));
memcpy(b,bb,sizeof(bb));
(*addr1[i])(a);
(*addr1[i])(b);
for (j=;j<tot;j++)
a[j]=a[j]*b[j]%mod;
(*addr2[i])(a);
for (j=;j<tot;j++)
printf("%lld%c",a[j],j==tot-?'\n':' ');
}
return ;
}
/*
0
1000000
1000000 3
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
*/

对应下方的图片公式推导

tf  a0+a1  a1-a0

utf  a1    a0

 #include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
using namespace std;
#define ll long long const double eps=1e-;
const ll inf=1e9;
const ll mod=;
const int maxn=(<<)*; ///any n or <2n /**
补全为2^k
**/ ll aa[maxn],bb[maxn],a[maxn],b[maxn];
int tot;
ll mod_inv_2=(mod+)/; ///or
void fwt1(ll *a)
{
int cnt_pre,cnt_cur,i,j;
for (cnt_pre=,cnt_cur=;cnt_pre<tot;cnt_pre<<=,cnt_cur<<=)
for (i=;i<tot;i+=cnt_cur)
for (j=;j<cnt_pre;j++)
(a[i+j+cnt_pre]+=a[i+j])%=mod;
} void ufwt1(ll *a)
{
int cnt_pre,cnt_cur,i,j;
for (cnt_pre=tot>>,cnt_cur=tot;cnt_pre>;cnt_pre>>=,cnt_cur>>=)
// for (cnt_pre=1,cnt_cur=2;cnt_pre<tot;cnt_pre<<=1,cnt_cur<<=1)
for (i=;i<tot;i+=cnt_cur)
for (j=;j<cnt_pre;j++)
(a[i+j+cnt_pre]-=a[i+j]-mod)%=mod;
} ///and
void fwt2(ll *a)
{
int cnt_pre,cnt_cur,i,j;
for (cnt_pre=,cnt_cur=;cnt_pre<tot;cnt_pre<<=,cnt_cur<<=)
for (i=;i<tot;i+=cnt_cur)
for (j=;j<cnt_pre;j++)
(a[i+j]+=a[i+j+cnt_pre])%=mod;
} void ufwt2(ll *a)
{
int cnt_pre,cnt_cur,i,j;
for (cnt_pre=tot>>,cnt_cur=tot;cnt_pre>;cnt_pre>>=,cnt_cur>>=)
// for (cnt_pre=1,cnt_cur=2;cnt_pre<tot;cnt_pre<<=1,cnt_cur<<=1)
for (i=;i<tot;i+=cnt_cur)
for (j=;j<cnt_pre;j++)
(a[i+j]-=a[i+j+cnt_pre]-mod)%=mod;
} ///xor
void fwt3(ll *a)
{
int cnt_pre,cnt_cur,i,j;
ll x;
for (cnt_pre=,cnt_cur=;cnt_pre<tot;cnt_pre<<=,cnt_cur<<=)
for (i=;i<tot;i+=cnt_cur)
for (j=;j<cnt_pre;j++)
{
x=a[i+j];
(a[i+j]+=a[i+j+cnt_pre])%=mod;
(a[i+j+cnt_pre]-=x-mod)%=mod; ///-x
}
} void ufwt3(ll *a)
{
int cnt_pre,cnt_cur,i,j;
ll x;
for (cnt_pre=tot>>,cnt_cur=tot;cnt_pre>;cnt_pre>>=,cnt_cur>>=)
// for (cnt_pre=1,cnt_cur=2;cnt_pre<tot;cnt_pre<<=1,cnt_cur<<=1)
for (i=;i<tot;i+=cnt_cur)
for (j=;j<cnt_pre;j++)
{
x=a[i+j];
a[i+j]=(a[i+j]+a[i+j+cnt_pre])*mod_inv_2%mod;
a[i+j+cnt_pre]=(x-a[i+j+cnt_pre]+mod)*mod_inv_2%mod; ///x-
}
} int main()
{
int n,i,j;
scanf("%d",&n);
tot=<<n;
for (i=;i<tot;i++)
scanf("%lld",&aa[i]);
for (i=;i<tot;i++)
scanf("%lld",&bb[i]); void (*addr1[]) (ll a[])={fwt1,fwt2,fwt3};
void (*addr2[]) (ll a[])={ufwt1,ufwt2,ufwt3}; for (i=;i<;i++)
{
memcpy(a,aa,sizeof(aa));
memcpy(b,bb,sizeof(bb));
(*addr1[i])(a);
(*addr1[i])(b);
for (j=;j<tot;j++)
a[j]=a[j]*b[j]%mod;
(*addr2[i])(a);
for (j=;j<tot;j++)
printf("%lld%c",a[j],j==tot-?'\n':' ');
}
return ;
}
/*
0
1000000
1000000 3
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
*/

and,or,xor等操作

C=A@B @为卷积运算(通过两个函数生成第三个函数的一种数学算子)

目标:tf(C)=tf(A)*tf(B)

设置tf(X)=(... , ...) 使满足上述条件

基础部分

公式推导

验证公式正确性

快速沃尔什变换(FWT) 与 快速莫比乌斯变换 与 快速沃尔什变换公式推导的更多相关文章

  1. 集合并卷积的三种求法(分治乘法,快速莫比乌斯变换(FMT),快速沃尔什变换(FWT))

    也许更好的阅读体验 本文主要内容是对武汉市第二中学吕凯风同学的论文<集合幂级数的性质与应用及其快速算法>的理解 定义 集合幂级数 为了更方便的研究集合的卷积,引入集合幂级数的概念 集合幂级 ...

  2. 快速沃尔什变换&快速莫比乌斯变换小记

    u1s1 距离省选只剩 5 days 了,现在学新算法真的合适吗(( 位运算卷积 众所周知,对于最普通的卷积 \(c_i=\sum\limits_{j+k=i}a_jb_k\),\(a_jb_k\) ...

  3. HDU 5977 Garden of Eden (树形dp+快速沃尔什变换FWT)

    CGZ大佬提醒我,我要是再不更博客可就连一月一更的频率也没有了... emmm,正好做了一道有点意思的题,就拿出来充数吧=.= 题意 一棵树,有 $ n (n\leq50000) $ 个节点,每个点都 ...

  4. 一个数学不好的菜鸡的快速沃尔什变换(FWT)学习笔记

    一个数学不好的菜鸡的快速沃尔什变换(FWT)学习笔记 曾经某个下午我以为我会了FWT,结果现在一丁点也想不起来了--看来"学"完新东西不经常做题不写博客,就白学了 = = 我没啥智 ...

  5. 快速沃尔什变换FWT

    快速沃尔什变换\(FWT\) 是一种可以快速完成集合卷积的算法. 什么是集合卷积啊? 集合卷积就是在集合运算下的卷积.比如一般而言我们算的卷积都是\(C_i=\sum_{j+k=i}A_j*B_k\) ...

  6. BZOJ4589 Hard Nim(快速沃尔什变换FWT)

    这是我第一道独立做出来的FWT的题目,所以写篇随笔纪念一下. (这还要纪念,我太弱了) 题目链接: BZOJ 题目大意:两人玩nim游戏(多堆石子,每次可以从其中一堆取任意多个,不能操作就输).$T$ ...

  7. 快速莫比乌斯变换(FMT)

    快速莫比乌斯变换(FMT) 原文出处:虞大的博客.此仅作蒟蒻本人复习用~ 给定两个长度为n的序列 \(a_0, a_1, \cdots, a_{n-1}\)和\(b_0, b_1, \cdots, b ...

  8. 【学习笔鸡】快速沃尔什变换FWT

    [学习笔鸡]快速沃尔什变换FWT OR的FWT 快速解决: \[ C[i]=\sum_{j|k=i} A[j]B[k] \] FWT使得我们 \[ FWT(C)=FWT(A)*FWT(B) \] 其中 ...

  9. 【learning】快速沃尔什变换FWT

    问题描述 已知\(A(x)\)和\(B(x)\),\(C[i]=\sum\limits_{j\otimes k=i}A[j]*B[k]\),求\(C\) 其中\(\otimes\)是三种位运算的其中一 ...

随机推荐

  1. NSDateFormatter 今年日期格式化成字符串是明年日期问题?

    在项目里我要是把NSDate格式化成字符串 我的format是@"YYYY年MM月dd日 HH:mm" 传入日期2013-12-30 15:00:00后,返回给我的字符串是 201 ...

  2. 其它课程中的python---2、NumPy模块

    其它课程中的python---2.NumPy模块 一.总结 一句话总结: numpy在数组计算方面又快又方便 1.NumPy中的ndarray是一个多维数组对象,该对象由哪两部分组成? -实际的数据 ...

  3. DLL劫持技术例子: HijackDll

    控制台程序:DllLoader Dll加载器,用于动态加载目标Dll,并动态调用目标函数 #include <cstdio> #include <windows.h> type ...

  4. java执行顺序之深入理解clinit和init

    原文地址:https://blog.csdn.net/qq_36522306/article/details/80582758 前言: 最近研究了深入理解JVM这本书中的知识,对java中各部分执行的 ...

  5. css3 常用的属性

    1.伪类选择符 Pseudo-Classes Selectors Selectors选择符 CSS Version版本 Description简介 E:link CSS1 设置超链接a在未被访问前的样 ...

  6. solr +zookeeper+Jetty 集群搭建

    solr版本:4.10.4 这里使用solr自带的jetty内置服务器 zk集群的 安装参照上篇文章: 在节点1example下上启动solr服务: java -DzkHost=192.168.0.1 ...

  7. uoj139 【UER #4】被删除的黑白树

    题目 不难发现有一个暴力\(dp\) 设\(dp[x][l]\)表示\(x\)点子树内所有叶子节点到\(x\)的路径上都有\(l\)和黑点时最多能染多个黑点 转移就是 \[dp[x][l]=\max( ...

  8. 004-Java进制转换

    整型数据共有4中进制形式 二进制(binary):以0b或者0B开头 十进制(decimal) 八进制(octal):以数字0开头 十六进制(hex):以0x或者0X开头 二进制数据包含原码反码和补码 ...

  9. ConvertBSTRToString导致的内存泄漏

    函数原型 char* __stdcall ConvertBSTRToString(BSTR pSrc); 这个指针指向的是一块动太分配的内存,如果把这个函数做为其它函数的参数,那么这块内存就会被泄漏掉 ...

  10. JMeter设置响应数据的编码格式

    1.修改配置文件jmeter.properties第974行,默认编码格式为ISO-8859-1,手动修改为UTF-8 2.增加元器件 在线程组右键,添加->后置处理器->BeanShel ...