牛客网比赛216C-小K的疑惑-题解
题目地址【IN】
写了一遍就过了,ヾ(◍°∇°◍)ノ゙凯森
题意简述
给你一棵个节点的树,每条边有边权,定义为点到的距离模后的值,问你有多少个三元组满足且。
数据范围
我们可以发现
那么就变成了的路径权值异或和。
那么,由于,异或是可以相消的,所以我们可以处理一个数组,表示节点到根(这里默认根为号点)的路径上的异或和,那么,原因如下图:
的路径上有
的路径上有
那么将,其中重复的边就会被异或掉,然后剩下的就变成了了。
所以
那么由于只有的时候才会成为一个合法的三元组,而的值只有,所以统计一下个数,我们令分别为的个数,那么答案就为(由于可以交换顺序,所以方案数为个数的三次方)。
代码非常简单:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int M=1e5+10;
struct ss{
int to,last,len;
ss(){}
ss(int a,int b,int c):to(a),last(b),len(c){}
}g[M<<1];
int head[M],cnt;
void add(int a,int b,int c){
g[++cnt]=ss(b,head[a],c&1);head[a]=cnt;
g[++cnt]=ss(a,head[b],c&1);head[b]=cnt;
}
ll rec[2];
void dfs(int a,int b,int val){
++rec[val];
for(int i=head[a];i;i=g[i].last){
if(g[i].to==b) continue;
dfs(g[i].to,a,val^g[i].len);
}
}
ll cude(ll a){return a*a*a;}
int a,b,c,n;
int main(){
scanf("%d",&n);
for(int i=1;i<n;i++){
scanf("%d%d%d",&a,&b,&c);
add(a,b,c);
}
dfs(1,0,0);
printf("%lld\n",cude(rec[0])+cude(rec[1]));
return 0;
}