UOJ #192. 【UR #14】最强跳蚤

Description

一棵树,给每一条边一个权值 \(w_i\),求出所有满足权值之积为完全平方数的路径的条数
题面

Sulotion

是完全平方数的充要条件是质因子出现次数为偶数,那么我们给每一个质因子一个随机一个权值,那么满足条件的路径就是异或和为 \(0\) 的路径
\(dsu\) 做一下就好了(别管我这个傻逼)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10,M=1e4+10;
int n,prime[M],num=0,t[N];bool vis[M];
int head[N],nxt[N*2],to[N*2],NUM=0;
ll c[N*2],sed=41,LIM=1e15,ans=0,b[N];
inline void link(int x,int y,ll z){
	nxt[++NUM]=head[x];to[NUM]=y;head[x]=NUM;c[NUM]=z;
	nxt[++NUM]=head[y];to[NUM]=x;head[y]=NUM;c[NUM]=z;
}
inline void priwork(){
	for(int i=2;i<M;i++){
		if(!vis[i])prime[++num]=i;
		for(int j=1;j<=num && i*prime[j]<M;j++){
			vis[i*prime[j]]=1;
			if(i%prime[j]==0)break;
		}
	}
}
map<int,ll>A;
inline ll seed(){return sed=(sed*41+99241)%LIM;}
inline ll F(int x){
	if(A.find(x)!=A.end())return A[x];
	return A[x]=seed();
}
inline ll getval(int x){
	ll ret=0;
	for(int i=1;i<=num;i++){
		if(x<prime[i])break;
		if(x%prime[i]==0){
			ll w=F(prime[i]);
			while(x%prime[i]==0)ret^=w,x/=prime[i];
		}
	}
	if(x>1)ret^=F(x);
	return ret;
}
int sz[N],son[N];ll dis[N];
inline void dfs1(int x){
	sz[x]=1;
	for(int i=head[x],u;i;i=nxt[i]){
		if(sz[u=to[i]])continue;
		dis[u]=dis[x]^c[i];dfs1(u);sz[x]+=sz[u];
		if(sz[son[x]]<sz[u])son[x]=u;
	}
}
inline void add(int x,int last){
	t[dis[x]]++;
	for(int i=head[x];i;i=nxt[i])if(to[i]^last)add(to[i],x);
}
inline void del(int x,int last){
	t[dis[x]]=0;
	for(int i=head[x];i;i=nxt[i])if(to[i]^last)del(to[i],x);
}
inline void cal(int x,int last){
	ans+=t[dis[x]];
	for(int i=head[x];i;i=nxt[i])if(to[i]^last)cal(to[i],x);
}
inline void dfs(int x,int last){
	for(int i=head[x];i;i=nxt[i])
		if(to[i]!=last && to[i]!=son[x])dfs(to[i],x),del(to[i],x);
	if(son[x])dfs(son[x],x);
	for(int i=head[x];i;i=nxt[i])
		if(to[i]!=last && to[i]!=son[x])cal(to[i],x),add(to[i],x);
	ans+=t[dis[x]];t[dis[x]]++;
}
int main(){
  freopen("pp.in","r",stdin);
  freopen("pp.out","w",stdout);
  scanf("%d",&n);
  priwork();
  int x,y,z;
  for(int i=1;i<n;i++){
	  scanf("%d%d%d",&x,&y,&z);
	  link(x,y,getval(z));
  }
  dfs1(1);
  for(int i=1;i<=n;i++)b[i]=dis[i];
  sort(b+1,b+n+1);
  int tp=unique(b+1,b+n+1)-b-1;
  for(int i=1;i<=n;i++)dis[i]=lower_bound(b+1,b+tp+1,dis[i])-b;
  dfs(1,1);
  cout<<ans*2<<endl;
  return 0;
}

posted @ 2018-07-15 11:42  PIPIBoss  阅读(161)  评论(0编辑  收藏  举报