HDU4670 cube number on a tree(点分治+三进制加法)
There are n provinces in the country. According to the experiences from the tourists came before, every province has its own preference value. A route’s preference value from one province to another is defined as the product of all the preference value of the provinces on the route. It’s guaranteed that for each two provinces in the country there is a unique route from one to another without passing any province twice or more.
Tom is a boy crazy about cube number. A cube number is a positive integer whose cube root is also an integer. He is planning to travel from a province to another in the summer vacation and he will only choose the route with the cube number preference value. Now he want to know the number of routes that satisfy his strange requirement.
Input
The input contains several test cases, terminated by EOF.
Each case begins with a number n ( 1 ≤ n ≤ 50000), the number of the provinces.
The second line begins with a number K (1 ≤ K ≤ 30), and K difference prime numbers follow. It’s guaranteed that all the preference number can be represented by the product of some of this K numbers(a number can appear multiple times).
The third line consists of n integer numbers, the ith number indicating the preference value P i(0 ≤ P i ≤ 10 15) of the i-th province.
Then n - 1 lines follow. Each line consists of two integers x, y, indicating there is a road connecting province x and province y.
Output
For each test case, print a number indicating the number of routes that satisfy the requirement.Sample Input
5
3 2 3 5
2500 200 9 270000 27
4 2
3 5
2 5
4 1
Sample Output
1
题解:
题意:给你一棵树,给你一些素数,给你每个点一个权值且每个权值均可由这些素数组成。现在定义任意任意两点的价值为他们路径上的权值相乘。求这样的点对的权值为立方数的个数
如果直接求得话会超int64,不可行
由立方数的性质可得,一个数可有素数组成,对于这些素数可以分解为这些素数相乘的形式如,24=(2^3)*(3^1);如果是立方数的话那么他的各进制对3取余都为0.股24可写成01这种三进制形式
对于这些权值的乘法可有三进制想加可得。
接下来就是树的分治了
当然这里可以先求出一条子树上的各个点的权值乘积,然后和根节点和其他字树比较看是否可以互补那么就找到一对
可用map容器实现。因为他重点是比较到根节点和其他子树是否可以互补,进而递归下去,求出每个子树的这样的点对
参考代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define fi first
#define se second
#define pii pair<int,int>
#define pil pair<int,ll>
#define mkp make_pair
#define pb push_back
const int INF=0x3f3f3f3f;
const ll inf=0x3f3f3f3f3f3f3f3fll;
inline ll read()
{
ll x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-') f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=(x<<)+(x<<)+ch-'';ch=getchar();}
return x*f;
}
const int maxn=1e5+;
ll n,k,head[maxn],tot,root,siz[maxn];
ll h[maxn][],pri[],fa[maxn],mx[maxn],S;
ll dep,ch[maxn][],fp[maxn],minn,nn;
bool vis[maxn];
map<ll,ll> mp;
struct Edge{
int v,nxt;
} edge[maxn<<]; inline void Init()
{
tot=;
memset(head,-,sizeof(head));
memset(h,,sizeof(h));
memset(mx,,sizeof(mx));
memset(siz,,sizeof(siz));
memset(vis,false,sizeof(vis));
} inline void AddEdge(ll u,ll v)
{
edge[tot].v=v;
edge[tot].nxt=head[u];
head[u]=tot++;
} inline void dfs1(ll u,ll fa)
{
nn++;
for(int e=head[u];~e;e=edge[e].nxt)
{
ll v=edge[e].v;
if(v==fa||vis[v]) continue;
dfs1(v,u);
}
} inline void GetRoot(ll u,ll fa)
{
siz[u]=;
ll tit=;
for(ll e=head[u];~e;e=edge[e].nxt)
{
ll v=edge[e].v;
if(v==fa||vis[v]) continue;
GetRoot(v,u);
siz[u]+=siz[v];
tit=max(tit,siz[v]);
}
tit=max(tit,nn-siz[u]);
if(tit<minn) minn=tit,root=u;
}
inline void dfs2(ll u,ll fa)
{
//cout<<"dfs2"<<endl;
if(fa==-)
{
for(ll i=;i<=k;++i)
ch[dep][i]=h[u][i];
}
else
{
ll e=fp[fa];
for(ll i=;i<=k;++i)
ch[dep][i]=(h[u][i]+ch[e][i])%;
}
fp[u]=dep++;
for(ll e=head[u];~e;e=edge[e].nxt)
{
ll v=edge[e].v;
if(v!=fa&&!vis[v]) dfs2(v,u);
}
} inline ll work(ll u)
{
ll s1=,ans=;
mp.clear();
for(ll i=;i<=k;++i) s1=s1*+h[u][i];
if(s1==) ans++;
mp[s1]=;
for(ll e=head[u];~e;e=edge[e].nxt)
{
ll v=edge[e].v;
if(vis[v]) continue;
dep=;dfs2(v,-);
for(ll i=;i<dep;++i)
{
s1=;
for(ll j=;j<=k;++j)
s1=s1*+(-ch[i][j])%;
ans+=mp[s1];
}
for(ll i=;i<dep;++i)
{
s1=;
for(ll j=;j<=k;++j)
s1=s1*+(ch[i][j]+h[u][j])%;
mp[s1]++;
}
}
return ans;
} inline ll dfs(ll u)
{
nn=,minn=inf;
dfs1(u,-);
GetRoot(u,-);
vis[root]=;
ll ans=work(root);
for(ll e=head[root];~e;e=edge[e].nxt)
{
ll v=edge[e].v;
if(vis[v]) continue;
ans+=dfs(v);
}
return ans;
} int main()
{
while(~scanf("%lld",&n))
{
Init();
k=read();
for(ll i=;i<=k;++i) pri[i]=read(); for(ll i=;i<=n;++i)
{
ll kk,val=read();
for(ll j=;j<=k;++j)
{
kk=;
while(val%pri[j]==)
{
++kk;
val/=pri[j];
kk%=;
}
h[i][j]=kk;
}
}
for(ll i=;i<n;++i)
{
ll x,y;
x=read();y=read();
AddEdge(x,y);AddEdge(y,x);
}
//cout<<"1"<<endl;
printf("%lld\n",dfs());
} return ;
}
HDU4670 cube number on a tree(点分治+三进制加法)的更多相关文章
- HDU4670 Cube number on a tree 树分治
人生的第一道树分治,要是早点学我南京赛就不用那么挫了,树分治的思路其实很简单,就是对子树找到一个重心(Centroid),实现重心分解,然后递归的解决分开后的树的子问题,关键是合并,当要合并跨过重心的 ...
- [hdu4670 Cube number on a tree]点分治
题意:给一个N个带权节点的树,权值以给定的K个素数为因子,求路径上节点乘积为立方数的路径条数 思路:立方数的性质是每个因子的个数为3的倍数,那么每个因子只需要保存0-2三个状态即可,然后路径就可以转化 ...
- 【点分治】【map】【哈希表】hdu4670 Cube number on a tree
求树上点权积为立方数的路径数. 显然,分解质因数后,若所有的质因子出现的次数都%3==0,则该数是立方数. 于是在模意义下暴力统计即可. 当然,为了不MLE/TLE,我们不能存一个30长度的数组,而要 ...
- hdu 4670 Cube number on a tree(点分治)
Cube number on a tree Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/ ...
- HDU 4670 Cube number on a tree ( 树的点分治 )
题意 : 给你一棵树 . 树的每一个结点都有一个权值 . 问你有多少条路径权值的乘积是一个全然立方数 . 题目中给了你 K 个素数 ( K <= 30 ) , 全部权值都能分解成这k个素数 思路 ...
- HDU 4670 Cube number on a tree
divide and conquer on tree. #include <map> #include <vector> #include <cstdio> #in ...
- Square Number & Cube Number
Square Number: Description In mathematics, a square number is an integer that is the square of an in ...
- CodeChef - PRIMEDST Prime Distance On Tree 树分治 + FFT
Prime Distance On Tree Problem description. You are given a tree. If we select 2 distinct nodes unif ...
- 【BZOJ-1468】Tree 树分治
1468: Tree Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1025 Solved: 534[Submit][Status][Discuss] ...
随机推荐
- 实现 sqrt(x):二分查找法和牛顿法
最近忙里偷闲,每天刷一道 LeetCode 的简单题保持手感,发现简单题虽然很容易 AC,但若去了解其所有的解法,也可学习到不少新的知识点,扩展知识的广度. 创作本文的思路来源于:LeetCode P ...
- Eclipse添加自定义注释
首先介绍几个常用的注解: @author 作者名 @date 日期 @version 版本标识 @parameter 参数及其意义 @return 返回值 @throws 异常类及抛出条件 @depr ...
- Windows键盘无法调起
Windows 键盘无法调起 经常使用触摸屏幕的小伙伴肯定都遇到过屏幕键盘怎么也唤不起来(在桌面模式下,非平板模式).以下收集了一些常见的解决方案: 注:本文基于 Windows 10 v1903,其 ...
- Docker学习-Docker搭建Consul集群
1.环境准备 Linux机器三台 网络互通配置可以参考 https://www.cnblogs.com/woxpp/p/11858257.html 192.168.50.21 192.168.50.2 ...
- [剑指offer]删除链表中重复的结点(把重复的都删掉,1个不留)
①题目 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针. 例如,链表1->2->3->3->4->4->5 处理后为 ...
- Python3.7.1(四) Print如何在输出中插入变量
# 如果想在打印的字符串中的任意地方加入任意的变量,可以使用python的格式化输出.## 用例代码如下:s = 'Hello'x = len(s)print("The length of ...
- iOS核心动画高级技巧 - 3
7. 隐式动画 隐式动画 按照我的意思去做,而不是我说的. -- 埃德娜,辛普森 我们在第一部分讨论了Core Animation除了动画之外可以做到的任何事情.但是动画是Core Animation ...
- vue在移动端实现复制数值到剪贴版
实现按键就指定内容复制到设备的剪贴版,这里是复制快递单号 html <div slot="footer" v-if="express.number" st ...
- Kibana创建索引成功,但一直不显示出来(Fielddata is disabled on text fields by default. Set fielddata=true........)
现象 把EFK整个集群搭建完成后,通过Kibana操作界面创建索引(如图1),我创建了lile-zabbix*的索引,显示是创建成功了,但是只要我在重新刷新一次,已经创建的索引就“消失了”.后通过查看 ...
- 使用图数据库 Nebula Graph 数据导入快速体验知识图谱 OwnThink
前言 本文由 Nebula Graph 实习生@王杰贡献. 最近 @Yener 开源了史上最大规模的中文知识图谱--OwnThink(链接:https://github.com/ownthink/Kn ...