• [ABC201E] Xor Distances


    前言

    很基础的一道树形DP题。

    题目

    AtCoder

    题目大意:

    给定一棵 (N) 个点的带权树,询问每个无序点对间的异或距离和。答案对 (10^9+7) 取模。

    (2le Nle 2 imes 10^5;0le w_ile 2^{60}.)

    讲解

    先考虑边权是 (0,1) 怎么做。

    显然可以直接DP,令 (dp[i][j]) 表示从下往上到 (i) 异或距离为 (j) 的路径数。转移很显然:

    [dp[u][i]=underset{vin son_x}{sum}dp[v][ioplus w_{u,v}]+(ioplus w_{u,v}oplus 1) ]

    中途顺便统计答案即可。

    由于每个二进制位之间不会互相影响,所以我们对于每一位单独做即可。

    时间复杂度:(O(nlog_2max{w_i}))

    当然你也可以从上往下做,用经典结论 (dis_{1,u}oplus dis_{1,v}=dis{u,v}) 计数。

    其实本质是相同的。

    注意long long 的使用以及溢出问题。

    代码

    从下往上。

    int head[MAXN],tot;
    struct edge
    {
    	int v,nxt;
    	LL w;
    }e[MAXN << 1];
    void Add(LL x){ans = (ans + x) % MOD;}
    void Add_Edge(int x,int y,LL z)
    {
    	e[++tot].v = y;
    	e[tot].w = z;
    	e[tot].nxt = head[x];
    	head[x] = tot;
    }
    void Add_Double_Edge(int x,int y,LL z)
    {
    	Add_Edge(x,y,z);
    	Add_Edge(y,x,z);
    }
     
    LL dp[MAXN][2];
    void dfs(int x,int fa,int o)
    {
    	dp[x][0] = dp[x][1] = 0;
    	for(int i = head[x]; i ;i = e[i].nxt)
    	{
    		int v = e[i].v,w = (e[i].w >> o) & 1;
    		if(v == fa) continue;
    		dfs(v,x,o);
    		if(!w)
    		{
    			Add(dp[x][0] * dp[v][1] % MOD * ((1ll << o) % MOD));
    			Add(dp[x][1] * (dp[v][0]+1) % MOD * ((1ll << o) % MOD));
    			dp[x][0] += dp[v][0]+1;
    			dp[x][1] += dp[v][1];
    		}
    		else 
    		{
    			Add(dp[x][0] * (dp[v][0]+1) % MOD * ((1ll << o) % MOD));
    			Add(dp[x][1] * dp[v][1] % MOD * ((1ll << o) % MOD));
    			dp[x][0] += dp[v][1];
    			dp[x][1] += dp[v][0]+1;
    		}
    	}
    	Add(dp[x][1] * ((1ll << o) % MOD));
    }
     
    int main()
    {
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	n = Read();
    	for(int i = 1;i < n;++ i)
    	{
    		int u = Read(),v = Read();
    		Add_Double_Edge(u,v,Read());
    	}
    	for(int i = 0;i <= 60;++ i) dfs(1,0,i);
    	Put(ans);
    	return 0;
    }
    
  • 相关阅读:
    HNOI2008玩具装箱
    CEOI2004锯木厂选址
    APIO2010特别行动队
    【HNOI2011】数学作业
    【JLOI2015】城池攻占
    魔法猪学院
    Kruskal重构树(货车运输)
    旋转卡壳求凸包直径
    Graham凸包算法简介
    poj-3169Layout
  • 原文地址:https://www.cnblogs.com/PPLPPL/p/14773419.html
Copyright © 2020-2023  润新知