• [hdu5909]Tree Cutting——动态规划+FWT


    题目大意:

    给定一棵树,求有多少个联通块满足异或和=k,对于每一个k求答案。

    思路:

    (dp_{i,j})表示联通块深度最小的点为i时,异或和为j时有多少个满足条件。
    从儿子转移,FWT优化即可。

    /*=======================================
     * Author : ylsoi
     * Time : 2019.2.10
     * Problem : hdu5909
     * E-mail : ylsoi@foxmail.com
     * ====================================*/
    #include<bits/stdc++.h>
    
    #define REP(i,a,b) for(int i=a,i##_end_=b;i<=i##_end_;++i)
    #define DREP(i,a,b) for(int i=a,i##_end_=b;i>=i##_end_;--i)
    #define debug(x) cout<<#x<<"="<<x<<" "
    #define fi first
    #define se second
    #define mk make_pair
    #define pb push_back
    typedef long long ll;
    
    using namespace std;
    
    void File(){
    	freopen("hdu5909.in","r",stdin);
    	freopen("hdu5909.out","w",stdout);
    }
    
    template<typename T>void read(T &_){
    	_=0; T f=1; char c=getchar();
    	for(;!isdigit(c);c=getchar())if(c=='-')f=-1;
    	for(;isdigit(c);c=getchar())_=(_<<1)+(_<<3)+(c^'0');
    	_*=f;
    }
    
    const int maxn=1000+10;
    const int maxm=2048+10;
    const int mod=1e9+7;
    const int inv=(mod+1)/2;
    int T,n,m,w[maxn];
    vector<int>G[maxn];
    ll dp[maxn][maxm],ans[maxm];
    
    void fwt(ll *A,int ty){
    	for(int len=1;len<m;len<<=1)
    		for(int L=0;L<m;L+=len<<1)
    			REP(i,L,L+len-1){
    				ll x=A[i],y=A[i+len];
    				A[i]=(x+y)%mod;
    				A[i+len]=(x-y)%mod;
    				if(ty==-1)A[i]=A[i]*inv%mod,A[i+len]=A[i+len]*inv%mod;
    			}
    }
    
    void dfs(int u,int fh){
    	REP(i,0,m)dp[u][i]=0;
    	dp[u][w[u]]=1;
    	fwt(dp[u],1);
    	REP(i,0,G[u].size()-1){
    		int v=G[u][i];
    		if(v==fh)continue;
    		dfs(v,u);
    		REP(j,0,m-1)dp[u][j]=dp[u][j]*dp[v][j]%mod;
    	}
    	fwt(dp[u],-1),++dp[u][0],fwt(dp[u],1);
    }
    
    int main(){
    	File();
    	read(T);
    	while(T--){
    		read(n),read(m);
    		REP(i,1,n)read(w[i]);
    		int u,v;
    		REP(i,1,n-1){
    			read(u),read(v);
    			G[u].pb(v);
    			G[v].pb(u);
    		}
    		dfs(1,0);
    		REP(i,1,n)fwt(dp[i],-1);
    		REP(i,0,m-1){
    			ans[i]=0;
    			REP(j,1,n)ans[i]=(ans[i]+dp[j][i])%mod;
    			if(!i)ans[i]=((ans[i]-n)%mod+mod)%mod;
    			printf("%lld%c",ans[i],i==m-1 ? '
    ' : ' ');
    		}
    		REP(i,1,n)G[i].clear();
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    Algs4-2.3.11快排遇与切分值相同时继续扫描是平方级
    使用kubeadm搭建Kubernetes集群
    kubernetes发布解释型语言应用的最佳实践
    docker化php项目发布方式
    linux服务器免密钥登录
    cp 递归复制时 复制实际文件而不是链接文件
    nginx配置http访问自动跳转到https
    nfs服务器
    nginx防止恶意域名解析
    如何建立自己的知识体系?(摘)
  • 原文地址:https://www.cnblogs.com/ylsoi/p/10359368.html
Copyright © 2020-2023  润新知