HDU 5909 Tree Cutting 树形DP+快速沃尔什变换
2016-10-14 16:11
423 查看
题目大意:给出一棵树,每个点有一个点权,求对于每个i∈[0,m)输出有多少个连通诱导子图的异或和为i
n≤1000,m<210
别问我为什么隔了这么久突然跑回来更blog……我只是在填以前剩下的坑而已。。。
(我花了一整个高三去打游戏,然后花了一整个大一补高三的内容,到了大二,我退学了2333)
FWT
定义:
对于一个长为n=2k的数组A,定义A0为这个数组的前2k−1项,A1为这个数组的后2k−1项,A=(A0,A1)
A±B={A[0]±B[0],A[1]±B[1],...,A[n−1]±B[n−1]}
A∗B={A[0]∗B[0],A[1]∗B[1],...,A[n−1]∗B[n−1]}
A⊕B={∑i⊕j=0A[i]∗B[j],...,∑i⊕j=n−1A[i]∗B[j]}
=(A0⊕B0+A1⊕B1,A0⊕B1+A1⊕B0)
易证⊕运算满足交换律和结合律,且由乘法分配律易得:
A⊕(B+C)=A⊕B+A⊕C
定义Fwt(A)为定义在数组A上的一个运算,定义如下:
Fwt(A)={(Fwt(A0+A1),Fwt(A0−A1))An>1n=1
性质1:
Fwt(A±B)=Fwt(A)±Fwt(B)
证明:容易发现Fwt(A)的每一项都是A[0],A[1],...,A[n−1]的一个线性组合,故对加法满足分配律
性质2:
Fwt(A⊕B)=Fwt(A)∗Fwt(B)
证明:数学归纳法
n=1时显然成立
设该公式对于长度n/2的数组均成立,则:
Fwt(A⊕B)
=Fwt(A0⊕B0+A1⊕B1,A0⊕B1+A1⊕B0)
=(Fwt(A0⊕B0+A1⊕B1+A0⊕B1+A1⊕B0) ,
Fwt(A0⊕B0+A1⊕B1−A0⊕B1−A1⊕B0) )
=(Fwt((A0+A1)⊕(B0+B1)),Fwt((A0−A1)⊕(B0−B1)) )
=(Fwt(A0+A1)∗Fwt(B0+B1),Fwt(A0−A1)∗Fwt(B0−B1))
=(Fwt(A)0∗Fwt(B)0,Fwt(A)1∗Fwt(B)1)
=Fwt(A)∗Fwt(B)
公式真尼玛长- - 是我证麻烦了么- -
这样我们就可以在O(n)的时间内计算A⊕B了……等等
逆运算呢?
……
Dwt(Fwt(A))=Dwt(Fwt(A0+A1),Fwt(A0−A1))
=Dwt(Fwt(A0)+Fwt(A1),Fwt(A0)−Fwt(A1))
令Dwt(A)=(Dwt(A0+A12),Dwt(A0−A12))
则
Dwt(Fwt(A))=(Dwt(Fwt(A0)),Dwt(Fwt(A1)))
=(A0,A1)=A
完美。
变换时间复杂度O(nlogn),计算时间复杂度O(n),逆变换时间复杂度O(nlogn)。
回来看题,令f[x][j]表示第x个点为根的连通诱导子图中异或和为j的数量,那么f[x]={0,0,...,0,1,0,...}⊕(f[y]+{1,0,0,...}),其中第一个数组的第a[x]位为1,其余都为0
用Fwt加速运算,时间复杂度O(mlogm+nm)
n≤1000,m<210
别问我为什么隔了这么久突然跑回来更blog……我只是在填以前剩下的坑而已。。。
(我花了一整个高三去打游戏,然后花了一整个大一补高三的内容,到了大二,我退学了2333)
FWT
定义:
对于一个长为n=2k的数组A,定义A0为这个数组的前2k−1项,A1为这个数组的后2k−1项,A=(A0,A1)
A±B={A[0]±B[0],A[1]±B[1],...,A[n−1]±B[n−1]}
A∗B={A[0]∗B[0],A[1]∗B[1],...,A[n−1]∗B[n−1]}
A⊕B={∑i⊕j=0A[i]∗B[j],...,∑i⊕j=n−1A[i]∗B[j]}
=(A0⊕B0+A1⊕B1,A0⊕B1+A1⊕B0)
易证⊕运算满足交换律和结合律,且由乘法分配律易得:
A⊕(B+C)=A⊕B+A⊕C
定义Fwt(A)为定义在数组A上的一个运算,定义如下:
Fwt(A)={(Fwt(A0+A1),Fwt(A0−A1))An>1n=1
性质1:
Fwt(A±B)=Fwt(A)±Fwt(B)
证明:容易发现Fwt(A)的每一项都是A[0],A[1],...,A[n−1]的一个线性组合,故对加法满足分配律
性质2:
Fwt(A⊕B)=Fwt(A)∗Fwt(B)
证明:数学归纳法
n=1时显然成立
设该公式对于长度n/2的数组均成立,则:
Fwt(A⊕B)
=Fwt(A0⊕B0+A1⊕B1,A0⊕B1+A1⊕B0)
=(Fwt(A0⊕B0+A1⊕B1+A0⊕B1+A1⊕B0) ,
Fwt(A0⊕B0+A1⊕B1−A0⊕B1−A1⊕B0) )
=(Fwt((A0+A1)⊕(B0+B1)),Fwt((A0−A1)⊕(B0−B1)) )
=(Fwt(A0+A1)∗Fwt(B0+B1),Fwt(A0−A1)∗Fwt(B0−B1))
=(Fwt(A)0∗Fwt(B)0,Fwt(A)1∗Fwt(B)1)
=Fwt(A)∗Fwt(B)
公式真尼玛长- - 是我证麻烦了么- -
这样我们就可以在O(n)的时间内计算A⊕B了……等等
逆运算呢?
……
Dwt(Fwt(A))=Dwt(Fwt(A0+A1),Fwt(A0−A1))
=Dwt(Fwt(A0)+Fwt(A1),Fwt(A0)−Fwt(A1))
令Dwt(A)=(Dwt(A0+A12),Dwt(A0−A12))
则
Dwt(Fwt(A))=(Dwt(Fwt(A0)),Dwt(Fwt(A1)))
=(A0,A1)=A
完美。
变换时间复杂度O(nlogn),计算时间复杂度O(n),逆变换时间复杂度O(nlogn)。
回来看题,令f[x][j]表示第x个点为根的连通诱导子图中异或和为j的数量,那么f[x]={0,0,...,0,1,0,...}⊕(f[y]+{1,0,0,...}),其中第一个数组的第a[x]位为1,其余都为0
用Fwt加速运算,时间复杂度O(mlogm+nm)
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 1100 #define MOD 1000000007 using namespace std; struct edge{ int to,next; }table[M<<1]; int head[M],tot; void Add(int x,int y) { table[++tot].to=y; table[tot].next=head[x]; head[x]=tot; } int n,m,d; void FWT(int a[],int n,int type/*1-FWT,-1-DWT*/) { if(n==1) return ; for(int i=0;i<n>>1;i++) { a[i]+=a[i+(n>>1)]; a[i+(n>>1)]=a[i]-(a[i+(n>>1)]<<1); a[i]%=MOD;(a[i+(n>>1)]+=MOD)%=MOD; if(type==-1) { a[i]=(MOD+1ll>>1)*a[i]%MOD; a[i+(n>>1)]=(MOD+1ll>>1)*a[i+(n>>1)]%MOD; } } FWT(a,n>>1,type);FWT(a+(n>>1),n>>1,type); } struct abcd{ int a[M]; abcd() {} abcd(bool) { memset(a,0,sizeof a); } int& operator [] (int x) { return a[x]; } void FWT(int type) { ::FWT(a,d,type); } friend abcd operator + (abcd x,abcd y) { abcd z(true); for(int i=0;i<d;i++) z[i]=(x[i]+y[i])%MOD; return z; } friend abcd operator * (abcd x,abcd y) { abcd z(true); for(int i=0;i<d;i++) z[i]=((long long)x[i]*y[i])%MOD; return z; } }f[M],zero,ans; void Initialize() { for(d=1;d<m;d<<=1); memset(f,0,sizeof f); memset(&zero,0,sizeof zero); memset(&ans,0,sizeof ans); zero[0]=1;zero.FWT(1); memset(head,0,sizeof head); tot=1; } void Tree_DP(int x,int from) { for(int i=head[x];i;i=table[i].next) if(table[i].to!=from) { Tree_DP(table[i].to,x); f[x]=f[x]*(f[table[i].to]+zero); } ans=ans+f[x]; } int main() { int T; for(cin>>T;T;T--) { cin>>n>>m; Initialize(); for(int i=1,x;i<=n;i++) { scanf("%d",&x); f[i][x]=1; f[i].FWT(1); } for(int i=1,x,y;i<n;i++) { scanf("%d%d",&x,&y); Add(x,y);Add(y,x); } Tree_DP(1,0); ans.FWT(-1); for(int i=0;i<m;i++) printf("%d%c",ans[i],i==m-1?'\n':' '); } return 0; }
相关文章推荐
- HDU 5977 Garden of Eden (树形dp+快速沃尔什变换FWT)
- HDU 5909 Tree Cutting (树形dp+FWT)
- HDU 5909 Tree Cutting 动态规划 快速沃尔什变换
- HDU 5909 Tree Cutting [树形dp+FWT]【动态规划+数学】
- HDU 5909 Tree Cutting(树形DP+FWT)
- HDU - 5909 Tree Cutting 树形dp + fwt 优化异或卷积和
- HDU 5909 Tree Cutting (点分治+树形DP|FWT+树形DP)
- HDU - 5909 Tree Cutting 树形DP+fwt优化 或点分治(待补)
- 【HDU 5909】 Tree Cutting (树形依赖型DP+点分治)
- HDU 5909 Tree Cutting(FWT+树形DP)
- [树形DP FWT] HDU 5909 Tree Cutting
- hdu 5909 Tree Cutting [树形DP fwt]
- 【HDU 5909】Tree Cutting
- hdu 4003 树形dp+分组背包
- HDU 1011 Starship Troopers (树形DP+背包)
- hdu 4044 GeoDefense 树形dp+分组背包
- hdu 4003 树形dp+分组背包 2011大连赛区网络赛C
- HDU 1561 (树形DP+背包)
- hdu 1561 树形dp+分组背包
- hdu 3586 Information Disturbing 树形dp+二分