Codeforces Round #396 (Div. 2) E. Mahmoud and a xor trip 树形压位DP

 

题目链接:http://codeforces.com/contest/766/problem/E

Examples

input

3

1 2 3

1 2

2 3

out

10

 

题意:

  给你一棵n个点的树,每个点有点权,求所有不同的路径异或和的总和

题解:

  DP

  任选一个root,设定dp[i][j][0]为以i为最高点的路径异或和中,二进制上第j为分别是0,1的数量

  记录答案

 

#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define ls i<<1
#define rs ls | 1
#define mid ((ll+rr)>>1)
#define pii pair<int,int>
#define MP make_pair
typedef long long LL;
const long long INF = 1e17+1LL;
const double Pi = acos(-1.0);
const int N = 1e5+10, M = 1e3+20, mod = 1e9+7, inf = 2e9+10;
int n,a[N];
LL dp[N][40][2],ans;
vector<int  > G[N];
void dfs(int u,int fa) {
    for(int i = 0; i < 30; ++i)
        dp[u][i][(a[u]>>i)&1] = 1;
    ans+=a[u];
    for(int i = 0 ; i < G[u].size(); ++i) {
        int to = G[u][i];
        if(to == fa) continue;
        dfs(to,u);
        for(int j = 0; j < 30; ++j) {
            ans += 1LL*(1<<j)*(dp[u][j][1]*dp[to][j][0] + dp[u][j][0]*dp[to][j][1]);
        }
        for(int j = 0; j < 30; ++j) {
            int p = ((a[u]>>j)&1);
            dp[u][j][1] += dp[to][j][p^1],
            dp[u][j][0] += dp[to][j][p^0];
        }
    }
}
int main() {
    scanf("%d",&n);
    for(int i = 1; i <= n; ++i) scanf("%d",&a[i]);
    for(int i = 1; i < n; ++i) {
        int x,y;
        scanf("%d%d",&x,&y);
        G[x].push_back(y);
        G[y].push_back(x);
    }
    dfs(1,-1);
    cout<<ans<<endl;
    return 0;
}
View Code

 

posted @ 2017-03-05 14:07  meekyan  阅读(177)  评论(0编辑  收藏  举报