• HDU


    题意:树上每个节点有权值,定义一棵树的权值为所有节点权值异或的值。求一棵树中,连通子树值为[0,m)的个数。
    分析:
    (dp[i][j])为根为i,值为j的子树的个数。
    (dp[i][joplus k] = dp[i][joplus k] +dp[i][j] * dp[v][k]) ,但暴力枚举(dp[i][j] * dp[v][k]),每次的复杂度是(O(M^2))的,总的复杂度将是(O(NM^2)),N和M都是1e3,不行。
    实际上每次要求的,是个异或的卷积。可以用FWT来将复杂度优化至(O(NMlogM))

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN = (1<<10)+5;
    typedef long long LL;
    const int mod=  1e9+7;
    LL dp[1005][MAXN];
    LL ans[MAXN];
    LL a[1005];
    int N,M;
    LL qpow(LL a,LL n)
    {
        LL res=1;
        while(n){
            if(n &1) res = res* a%mod;
            a = a*a %mod;
            n>>=1;
        }
        return res;
    }
    LL rev2 = qpow(2,mod-2);
    
    void FWT(LL a[] ,int n){
        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++){
                    LL x = a[i+j],y = a[i+j+d];
                    a[i+j] = (x+y)%mod,a[i+j+d] = (x-y+mod)%mod;        //取模
                }
            }
        }
    }
    
    void UFWT(LL a[],int n){
        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++){
                    LL x = a[i+j],y = a[i+j+d];
                    a[i+j] = (x+y)*rev2%mod,a[i+j+d] = ((x-y)*rev2%mod + mod) % mod;  //取模的情况 
                }
            }
        }
    }
    void solve(LL a[],LL b[],int n){
        FWT(a,n);
        FWT(b,n);
        for (int i = 0 ; i<n ; i++)
            a[i]=a[i]*b[i] %mod;                 //取模
        UFWT(a,n);
    }
    
    struct Edge{
        int v,next;
    }edges[2005];
    int head[1005],tot;
    void init(){
        tot = 0;
        memset(head,-1,sizeof(head));
    }
    
    void AddEdge(int u,int v)
    {
        edges[tot] = (Edge){v,head[u]};
        head[u] = tot++;
    }
    LL tmp[MAXN];
    
    void dfs(int u,int fa)
    {
        dp[u][a[u]] = 1;
        for(int i=head[u];~i;i=edges[i].next){
            int v = edges[i].v;
            if(v== fa) continue;
            dfs(v,u);
            for(int i=0;i<M;++i){
                tmp[i] = dp[u][i];
            }
            solve(dp[u],dp[v],M);
            for(int i=0;i<M;++i){
                dp[u][i] = (dp[u][i] + tmp[i])%mod;     //将之前
            }
        }
        for(int i=0;i<M;++i){
            ans[i] = (ans[i]+ dp[u][i]) %mod;
        }
    }
    
    int main()
    {
        #ifndef ONLINE_JUDGE
            freopen("in.txt","r",stdin);
            freopen("out.txt","w",stdout);
        #endif
        int T; scanf("%d",&T);
        while(T--){
            init();
            memset(dp,0,sizeof(dp));
            memset(ans,0,sizeof(ans));
            scanf("%d %d",&N, &M);
            for(int i=1;i<=N;++i){
                scanf("%lld",&a[i]);
            }
            for(int i=1,u,v;i<=N-1;++i){
                scanf("%d %d",&u,&v);
                AddEdge(u,v);
                AddEdge(v,u);
            }
            dfs(1,-1);
            for(int i=0;i<M;++i){
                printf("%lld%c",ans[i],i==M-1?'
    ':' ');
            }
        }
        return 0;
    }
    
    
  • 相关阅读:
    C语言实现mq收发数据的函数
    4G通信模块在ARM平台下的应用
    4G 通信模块在ARM 平台下的应用
    修改web前端访问端口
    从零开始用 Flask 搭建一个网站(一)
    Python实现Windows定时关机
    前端和后端的数据交互(jquery ajax+python flask+mysql)
    python开源项目及示例代码
    Django读取Mysql数据并显示在前端
    C++关于string的一些用法
  • 原文地址:https://www.cnblogs.com/xiuwenli/p/9721134.html
Copyright © 2020-2023  润新知