zoukankan      html  css  js  c++  java
  • [HDU5909]Tree Cutting

    题目传送门:VjudgeHDU

    题目大意:

    给定一棵树,每个节点上有权值,定义一个树上联通块(S)的权值为(V_1oplus V_2oplus...oplus V_k(forall iin S)),问权值为(x(xin[0,m))的联通块个数


    考虑dp,设(f[i][j])表示以(i)为根,子数中权值为(j)的联通块个数,合并显然就是两个(f)异或卷积一下,FWT优化即可

    /*program from Wolfycz*/
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define inf 0x7f7f7f7f
    using namespace std;
    typedef long long ll;
    typedef unsigned int ui;
    typedef unsigned long long ull;
    inline char gc(){
    	static char buf[1000000],*p1=buf,*p2=buf;
    	return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
    }
    inline int frd(){
    	int x=0,f=1;char ch=gc();
    	for (;ch<'0'||ch>'9';ch=gc())	if (ch=='-')    f=-1;
    	for (;ch>='0'&&ch<='9';ch=gc())	x=(x<<1)+(x<<3)+ch-'0';
    	return x*f;
    }
    inline int read(){
    	int x=0,f=1;char ch=getchar();
    	for (;ch<'0'||ch>'9';ch=getchar())	if (ch=='-')	f=-1;
    	for (;ch>='0'&&ch<='9';ch=getchar())	x=(x<<1)+(x<<3)+ch-'0';
    	return x*f;
    }
    inline void print(int x){
    	if (x<0)    putchar('-'),x=-x;
    	if (x>9)	print(x/10);
    	putchar(x%10+'0');
    }
    const int N=1e3,M=1<<10,Mod=1e9+7,inv=5e8+4;
    void div(int &x){x=1ll*x*inv%Mod;}
    void FWT(int *a,int n,int flag){
    	for (int i=2;i<=n;i<<=1){
    		for (int j=0;j<n;j+=i){
    			for (int k=0;k<i>>1;k++){
    				int x=a[j+k],y=a[j+k+(i>>1)];
    				a[j+k]=(x+y)%Mod,a[j+k+(i>>1)]=(x-y+Mod)%Mod;
    				if (!~flag)	div(a[j+k]),div(a[j+k+(i>>1)]);
    			}
    		}
    	}
    }
    int pre[(N<<1)+10],now[N+10],child[(N<<1)+10];
    int f[N+10][M+10],Ans[M+10];
    int n,m,tot;
    void join(int x,int y){pre[++tot]=now[x],now[x]=tot,child[tot]=y;}
    void insert(int x,int y){join(x,y),join(y,x);}
    void dfs(int x,int fa){
    	FWT(f[x],m,1);
    	for (int p=now[x],son=child[p];p;p=pre[p],son=child[p]){
    		if (son==fa)	continue;
    		dfs(son,x);
    		for (int i=0;i<m;i++)	f[x][i]=1ll*f[x][i]*f[son][i]%Mod;
    	}
    	FWT(f[x],m,-1);
    	if (++f[x][0]==Mod)	f[x][0]=0;
    	FWT(f[x],m,1);
    }
    int main(){
    	for (int T=read();T;T--){
    		n=read(),m=read(),tot=0;
    		memset(f,0,sizeof(f));
    		memset(now,0,sizeof(now));
    		memset(Ans,0,sizeof(Ans));
    		for (int i=1;i<=n;i++)	f[i][read()]=1;
    		for (int i=1;i<n;i++){
    			int x=read(),y=read();
    			insert(x,y);
    		}
    		dfs(1,0);
    		for (int i=1;i<=n;i++)	FWT(f[i],m,-1);
    		for (int i=1;i<=n;i++)	if (--f[i][0]<0)	f[i][0]+=Mod;
    		for (int i=1;i<=n;i++)
    			for (int j=0;j<m;j++)
    				Ans[j]=(Ans[j]+f[i][j])%Mod;
    		for (int i=0;i<m;i++)	printf("%d",Ans[i]),putchar(i==m-1?'
    ':' ');
    	}
    	return 0;
    }
    
  • 相关阅读:
    口腔溃疡
    English 好的报纸
    线段树
    归并排序 霍纳规则(法则) 统计逆序对
    xfce4桌面自动整理脚本
    解决xubuntu的thunar第一次启动慢
    解决ibus图标为红圈(图标丢失)
    linux tar 备份命令
    ubuntu中的Wine详解
    我的conky配置
  • 原文地址:https://www.cnblogs.com/Wolfycz/p/10436314.html
Copyright © 2011-2022 走看看