zoukankan      html  css  js  c++  java
  • hdu 5909 Tree Cutting

    http://acm.hdu.edu.cn/showproblem.php?pid=5909

    题意:

    给出一颗带点权的树,输出有多少联通块的点权异或和=[1,m)

    dp[x][i] 以x为根的子树中,联通块内一定有x,目前异或和为i 的联通块 个数

    dp[x][i] =  dp[x][i] + Σ Σ [j^k==i] dp[x][j]^dp[son][k]

    时间复杂度为 n*m*m

    用FWT优化到 n*m*logm

    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<iostream>
    
    using namespace std;
    
    const int mod=1e9+7;
    
    #define N 1001
    const int M=(1<<10)+2;
    
    int m;
    int val[N];
    vector<int>V[N];
    
    int dp[N][M],tmp[M];
    int ans[M];
    
    long long inv;
    
    void read(int &x)
    {
        x=0; char c=getchar();
        while(!isdigit(c)) c=getchar();
        while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
    }
    
    void FWT_xor(int *a,int n)
    {
        int x,y;
        for(int d=1;d<n;d<<=1)
            for(int m=d<<1,i=0;i<n;i+=m)
                for(int j=0;j<d;++j)
                {
                    x=a[i+j]; y=a[i+j+d];
                    a[i+j]=(x+y)%mod; a[i+j+d]=(x-y+mod)%mod;
                }
    }
    
    void IFWT_xor(int *a,int n)
    {
        int x,y;
        for(int d=1;d<n;d<<=1)
            for(int m=d<<1,i=0;i<n;i+=m)
                for(int j=0;j<d;++j)
                {
                    x=a[i+j]; y=a[i+j+d];
                    a[i+j]=(x+y)*inv%mod; a[i+j+d]=((x-y)*inv%mod+mod)%mod;
                }
    }
    
    void solve(int *a,int *b,int n)
    {
        FWT_xor(a,n);
        FWT_xor(b,n);
        for(int i=0;i<n;++i) a[i]=(1LL*a[i]*b[i])%mod;
        IFWT_xor(a,n);
    }
    
    void dfs(int x,int fa)
    {
        dp[x][val[x]]=1;
        int siz=V[x].size(),t;
        for(int i=0;i<siz;++i)
        {
            t=V[x][i];
            if(t==fa) continue;
            dfs(t,x);
            for(int i=0;i<m;++i) tmp[i]=dp[x][i];
            solve(dp[x],dp[t],m);
            for(int i=0;i<m;++i) (dp[x][i]+=tmp[i])%=mod;
        }
        for(int i=0;i<m;++i) (ans[i]+=dp[x][i])%=mod;
    }
    
    long long Pow(long long a,int b)
    {
        long long res=1;
        for(;b;b>>=1,a=a*a%mod)
            if(b&1) res=res*a%mod;
        return res;
    }
    
    int main()
    {
        int T;
        int n,u,v;
        read(T);
        inv=Pow(2,mod-2);
        while(T--)
        {
            memset(dp,0,sizeof(dp));
            memset(ans,0,sizeof(ans));
            read(n); read(m);
            for(int i=1;i<=n;++i) read(val[i]);
            for(int i=1;i<=n;++i) V[i].clear();
            for(int i=1;i<n;++i)
            {
                read(u); read(v);
                V[u].push_back(v);
                V[v].push_back(u);
            }
            dfs(1,0);
            for(int i=0;i<m-1;++i) printf("%d ",ans[i]);
            printf("%d
    ",ans[m-1]);
        }
    }    
  • 相关阅读:
    一些Redis面试题
    PHP中类和对象
    PHP中普通方法和静态方法
    PHP中普通属性和静态属性
    PHP中对象的传值方式
    PHP创建对象的几种形式
    面向对象与面向过程思想区别
    mysql中联合查询
    mysql中用户和权限
    mysql中事务
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/8596594.html
Copyright © 2011-2022 走看看