题目链接

problem

给出一个n个点带边权的树,问有多少对\((u,v)\)满足\(u\)到\(v\)路径上边权的乘积为完全平方数。

\(n\le 10^5,w\le 10^8\)

solution

一个比较朴素的处理方法就是:设第i个质因子权值为\(2^{i-1}\),将每个边权质因子分解,并将所有质因子的权值异或起来,然后得到一个新的权值。这样问题就转化为了求有多少对\((u,v)\)满足从\(u\)到\(v\)路径上的权值异或和为0。直接书上前缀和一下就行。

但是当\(w=10^8\)时显然不行,考虑给每个质因子随机赋一个\([0,2^{64}]\)中的值,然后用同样的方法异或起来。这样满足条件的路径一定可以被找到。不满足条件的路径只有\(\frac{1}{2^{64}}\)误算。

然后考虑如何计算每个数字的质因子,先线性筛出\([1,\sqrt{w}]\)中的质因子,并对其重新赋权值。对于大于\(\sqrt{w}\)的质因子单独处理一下。

code

/*
* @Author: wxyww
* @Date: 2020-02-05 16:57:50
* @Last Modified time: 2020-02-05 18:21:14
*/
#include<map>
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<bitset>
#include<cstring>
#include<algorithm>
#include<string>
#include<queue>
#include<vector>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N = 100010;
ll read() {
ll x=0,f=1;char c=getchar();
while(c<'0'||c>'9') {
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9') {
x=x*10+c-'0';
c=getchar();
}
return x*f;
}
struct node {
int v,nxt;ull w;
}e[N << 1];
int head[N],ejs;
void add(int u,int v,ull w) {
e[++ejs].v = v;e[ejs].nxt = head[u];head[u] = ejs;e[ejs].w = w;
}
map<int,ull>ma;
ull Rand() {
return (ull)rand() * (ull)rand() * (ull)rand() * (ull)rand() * (ull)rand();
}
ull val[N];
int vis[N],pri[N],tot;
void pre() {
for(int i = 2;i <= 10000;++i) {
if(!vis[i]) {
pri[++tot] = i;
val[tot] = Rand();
}
for(int j = 1;j <= tot && i * pri[j] <= 10000;++j) {
vis[pri[j] * i] = 1;
if(i % pri[j] == 0) break;
}
}
}
ull get(int x) {
ull ret = 0;
for(int i = 1;i <= tot;++i) {
while(x % pri[i] == 0) {
x /= pri[i];
ret ^= val[i];
}
}
if(x != 1) {
if(!ma.count(x)) ma[x] = Rand();
ret ^= ma[x];
}
return ret;
}
ull dis[N];
ll anss;
map<ull,int>ans;
void dfs(int u,int fa) {
anss += ans[dis[u]] * 2;
ans[dis[u]]++;
for(int i = head[u];i;i = e[i].nxt) {
int v = e[i].v;if(v == fa) continue;
dis[v] = dis[u] ^ e[i].w;
dfs(v,u);
}
}
int main() {
pre();
int n = read();
for(int i = 1;i < n;++i) {
int u = read(),v = read();ull w = get(read());
add(u,v,w);add(v,u,w);
}
dfs(1,0);
cout<<anss;
return 0;
}

最新文章

  1. 【小贴士】【stringify神BUG】【localstorage失效】【消灭Safari alert框】【是否延迟加载】【页面10px白屏】
  2. EF分页中的陷阱
  3. javascript原型方法
  4. char,vchar,nchar,nvchar的区别
  5. android studio提示unable to run mksdcard sdk
  6. php数组去重的函数代码
  7. The Shapes of CSS
  8. gif图简介
  9. java核心技术学习笔记之三程序设计结构
  10. 如何使用 Android Studio 的 git hub 功能
  11. phpexcel用法(转)
  12. Vmware workstation V2V
  13. C# 执行DOS命令和批处理
  14. NLog的介绍使用
  15. 转:VIM选择文本块/复制/粘贴
  16. Debian/Ubuntu pip default install to $HOME/.local
  17. python中使用pillow绘制汉字
  18. JavaScript实现计时器
  19. 【贪心大水题】BZOJ3410-[Usaco2009 Dec]Selfish Grazing 自私的食草者
  20. 《Spark 官方文档》在Mesos上运行Spark

热门文章

  1. Kubernetes的pod控制器及ReplicaSet控制器类型的pod的定义
  2. 15. 深入解析Pod对象(二):使用进阶
  3. 吴裕雄--天生自然Numpy库学习笔记:NumPy 从已有的数组创建数组
  4. 吴裕雄 python 神经网络——TensorFlow 输入数据处理框架
  5. Docker 安装 Filebeat
  6. 【Fine学习笔记】Jmeter笔记
  7. vue 的模拟数据
  8. 使用IDEA导入一个Maven风格的SSM项目
  9. NGINX学习积累(学习牛人)
  10. ArcMap中字段计算器(Field Calculator)将数字类型转换为字符串类型