这题一开始想出来了一个用字典树维护的
O(w−−√+n∗π(w−−√))
,并用字典树维护,的方法,感觉常数爆炸。看了题解后感觉这题有点字符串题的味道,题解相当于把我的字典树换成了hash。但是,单预处理的1亿多次取模就会T吧(取模那么慢),于是心里不平衡,造了极限数据去卡人,不小心把本校学长qlj给hack了。
后来才发现,09年骗分导论上,写的什么取模操作每秒只能进行
8∗107
次,在如今的评测机面前,已经不现实了。
这是蒟蒻zx的AC记录
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<map>
#include<cstdlib>
#include<ctime>
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ul;
map<int,ul> m;
inline ul F(){
return 1ull*rand()*rand()*rand();
}
const int N=100010;
int n,a,b,c,i,p[N],xb,j;
bool bb[N];
inline ul got(int x){
int i,s;
ul ans=0;
for(i=1;p[i]*p[i]<=x && i<=xb;++i){
for(s=0;x%p[i]==0;x/=p[i])++s;
if(s&1){
if(!m[p[i]])m[p[i]]=F();
ans^=m[p[i]];
}
}
if(x>1){
if(!m[x])m[x]=F();
ans^=m[x];
}
return ans;
}
struct tree{
struct edge{
int to,next;
int w;
}e[N<<1];
int h[N],xb;
ul v[N];
void addedge(int x,int y,int z){
e[++xb]=(edge){y,h[x],z};
h[x]=xb;
}
void dfs(int x,int fa,ul f){
v[++xb]=f;
for(int i=h[x];i;i=e[i].next)if(fa!=e[i].to)dfs(e[i].to,x,f^got(e[i].w));
}
inline ll solve(){
xb=0;
dfs(1,0,0);
sort(v+1,v+n+1);
ll ans=0;
for(int i=1,j;i<=n;++i){
j=i;
while(v[i]==v[i+1] && i<=n)++i;
if(i>n)--i;
ans+=1ll*(i-j+1)*(i-j);
}
return ans;
}
}t;
int main(){
//freopen("ex_a3.in","r",stdin);
srand(time(0));
for(i=2;i<=10000;++i){
if(!bb[i])p[++xb]=i;
for(j=1;j<=xb;++j){
a=p[j]*i;
if(a>10000)break;
bb[a]=1;
if(i%p[j]==0)break;
}
}
scanf("%d",&n);
for(i=1;i<n;++i){
scanf("%d%d%d",&a,&b,&c);
t.addedge(a,b,c);
t.addedge(b,a,c);
}
cout<<t.solve()<<endl;
return 0;
}