Cube number on a tree

Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)
Total Submission(s): 1628    Accepted Submission(s): 382

Problem Description
The country Tom living in is famous for traveling. Every year, many tourists from all over the world have interests in traveling there.
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 Pi(0 ≤ Pi ≤ 1015) 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
hdu 4670 Cube number on a tree(点分治)

problem:
在一棵树上,求多少条路径的点权值积为立方数 solve:
和普通的求积为k的点对数很像.因为权值有10^15,所以用质因子来记录每个树的权值. 然后就是状态保存,因为当你知道当前子树的一条链时
,需要查找其它子树(同一根)是否有链与其对应使积为立方数. 质因子总共有30位,所以可以用一个longlong来记录状态,用map保存
(递归所有重心,每次计算当前重心的所有情况) hhh-2016-08-24 09:42:56
*/
#pragma comment(linker,"/STACK:124000000,124000000")
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <vector>
#include <math.h>
#include <map>
#define lson i<<1
#define rson i<<1|1
#define ll long long
#define clr(a,b) memset(a,b,sizeof(a))
#define scanfi(a) scanf("%d",&a)
#define scanfl(a) scanf("%I64d",&a)
#define key_val ch[ch[root][1]][0]
#define inf 0x3FFFFFFFFFFFFFFFLL
#define mod 1000003
using namespace std;
const ll xo = (1LL << 61)-1;
const int maxn = 50010;
int head[maxn];
int n,k,s[maxn],f[maxn],root;
int Size,tot;
bool vis[maxn];
ll factor[maxn][31],d[maxn][31],fac[31];
int facnt;
int id[maxn];
ll val;
struct node
{
int to;
int next;
} edge[maxn << 2]; void ini()
{
clr(factor,0);
clr(head,-1),clr(vis,0);
clr(s,0);
tot = 0;
} void add_edge(int u,int v)
{
edge[tot].to = v,edge[tot].next = head[u],head[u] = tot++;
} void get_root(int now,int fa)
{
int v;
s[now] = 1,f[now] = 0;
for(int i = head[now]; ~i; i = edge[i].next)
{
if((v=edge[i].to) == fa || vis[v])
continue;
get_root(v,now);
s[now] += s[v];
f[now] = max(f[now],s[v]);
}
f[now] = max(f[now],Size-s[now]);
if(f[now] < f[root]) root = now;
}
int num;
map<ll,ll> mp;
ll make_hash(ll q[])
{
ll t = 0; for(int i = 0; i < facnt; i++)
{
t = t*3LL + q[i];
} return t;
} void dfs(int now,int fa)
{
int v;
id[num++] = now;
s[now] = 1; for(int i = head[now]; ~i; i = edge[i].next)
{
if( (v=edge[i].to) == fa || vis[v])
continue;
for(int j = 0; j < facnt; j++)
{
d[v][j] = (factor[v][j]+d[now][j])%3;
}
dfs(v,now);
s[now] += s[v];
}
}
ll ans = 0;
ll tp[31];
void Debug(ll t)
{
for(int i = 30; i >= 0; i--)
{
if(t & (1 << i))
printf("1");
else
printf("0");
}
cout << endl;
}
void make_ans(int now,int cnt)
{
int v ;
f[0] = Size = cnt;
get_root(now,root = 0);
vis[root] = 1;
mp.clear();
ll ts = make_hash(factor[root]);
if(ts == 0)
ans ++; for(int i = head[root]; ~i; i = edge[i].next)
{
if(vis[v = edge[i].to])
continue;
num = 0;
for(int j = 0; j < facnt; j++)
d[v][j] = factor[v][j];
dfs(v,root); for(int j = 0; j < num; j++)
{
for(int t = 0; t < facnt; t++)
{
tp[t] = (d[id[j]][t] + factor[root][t])%3;
}
ll ta = make_hash(tp); if(ta == 0)
{
ans ++;
} ta = 0;
for(int t = 0; t < facnt; t++)
ta = ta*3LL + (3LL-tp[t])%3;
if(mp[ta] > 0)
{
ans += mp[ta];
}
}
for(int j = 0; j < num; j++)
{
ll ta = make_hash(d[id[j]]);
if(mp[ta] == -1)
mp[ta] = 0;
mp[ta] ++;
}
}
for(int i = head[root]; ~i; i = edge[i].next)
{
if(vis[v = edge[i].to])
continue;
make_ans(v,s[v]);
}
}
void make_fac(int u,ll cur)
{
ll t = cur;
for(int i = 0; i < facnt; i++)
{
while(t % fac[i] == 0)
{
t /= fac[i];
factor[u][i]++;
}
factor[u][i] %= 3;
}
} int main()
{
int n,u,v;
// freopen("in.txt","r",stdin);
while( scanfi(n) != EOF)
{
ini();
scanfi(facnt);
for(int i = 0; i < facnt; i++)
scanfl(fac[i]);
for(int i = 1; i<= n; i++)
{
scanfl(val);
make_fac(i,val); }
for(int i = 1; i < n; i++)
{
scanfi(u),scanfi(v);
add_edge(u,v);
add_edge(v,u);
}
ans =0;
make_ans(1,n);
printf("%I64d\n",ans);
}
return 0;
}

  

hdu 4670 Cube number on a tree(点分治)的更多相关文章

  1. HDU 4670 Cube number on a tree

    divide and conquer on tree. #include <map> #include <vector> #include <cstdio> #in ...

  2. HDU 4670 Cube number on a tree ( 树的点分治 )

    题意 : 给你一棵树 . 树的每一个结点都有一个权值 . 问你有多少条路径权值的乘积是一个全然立方数 . 题目中给了你 K 个素数 ( K <= 30 ) , 全部权值都能分解成这k个素数 思路 ...

  3. HDU4670 cube number on a tree(点分治+三进制加法)

    The country Tom living in is famous for traveling. Every year, many tourists from all over the world ...

  4. HDU4670 Cube number on a tree 树分治

    人生的第一道树分治,要是早点学我南京赛就不用那么挫了,树分治的思路其实很简单,就是对子树找到一个重心(Centroid),实现重心分解,然后递归的解决分开后的树的子问题,关键是合并,当要合并跨过重心的 ...

  5. [hdu4670 Cube number on a tree]点分治

    题意:给一个N个带权节点的树,权值以给定的K个素数为因子,求路径上节点乘积为立方数的路径条数 思路:立方数的性质是每个因子的个数为3的倍数,那么每个因子只需要保存0-2三个状态即可,然后路径就可以转化 ...

  6. 【点分治】【map】【哈希表】hdu4670 Cube number on a tree

    求树上点权积为立方数的路径数. 显然,分解质因数后,若所有的质因子出现的次数都%3==0,则该数是立方数. 于是在模意义下暴力统计即可. 当然,为了不MLE/TLE,我们不能存一个30长度的数组,而要 ...

  7. 主席树[可持久化线段树](hdu 2665 Kth number、SP 10628 Count on a tree、ZOJ 2112 Dynamic Rankings、codeforces 813E Army Creation、codeforces960F:Pathwalks )

    在今天三黑(恶意评分刷上去的那种)两紫的智推中,突然出现了P3834 [模板]可持久化线段树 1(主席树)就突然有了不详的预感2333 果然...然后我gg了!被大佬虐了! hdu 2665 Kth ...

  8. hdu 2665 Kth number

    划分树 /* HDU 2665 Kth number 划分树 */ #include<stdio.h> #include<iostream> #include<strin ...

  9. HDU - 3584 Cube (三维树状数组 + 区间改动 + 单点求值)

    HDU - 3584 Cube Time Limit: 1000MS   Memory Limit: 65536KB   64bit IO Format: %I64d & %I64u Subm ...

随机推荐

  1. Hibernate学习错误集锦-GenericJDBCException: could not execute statement

    初次使用Hibernate,进行junit测试,报如下错误. 原因:Hibernate帮我们管理主键了,我们不需要对主键赋值,并且主键是自增的.所以在数据库中,逐渐选项应当勾选 org.hiberna ...

  2. 开始 Python 之旅

    开始 Python 之旅 课程来源 本课程基于 Python for you and me 教程翻译制作,其中参考了 Python tutorial 和 The Python Standard Lib ...

  3. 《招一个靠谱的移动开发》iOS面试题及详解(下篇)

    iOS面试知识点 现在进入本篇的正题.本篇的面试题是我认为比较好的iOS开发基础知识点,希望大家看过这后在理解的基础上掌握而不是死记硬背.死记硬背很快也会忘记的. 1 iOS基础 1.1 父类实现深拷 ...

  4. 201421123042 《Java程序设计》第12周

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多流与文件相关内容. 2. 面向系统综合设计-图书馆管理系统或购物车 使用流与文件改造你的图书馆管理系统或购物车. 2.1 简述如何 ...

  5. win10 安装mingw ruby rails

    原文可以参考 https://ruby-china.org/topics/17581 在window10 安装ruby rails https://rubyinstaller.org/download ...

  6. loadrunner下载资源时步骤下载超时 (120 seconds) 已过期

    下载资源所用时间超过120秒时,就会报出这个错误,解决方法是设置加大超时时间 运行时设置(快捷键F4) Internet 协议--首选项--高级--选项--General--步骤下载超时(秒) 可以把 ...

  7. javascript参数传递中处理+号

    在传值过程中,如果+号也是值的一部分,那就需要对+号进行处理.否则+号会被过滤掉. 处理方式:只需要把js中传过去的+号替换成base64 编码 %2B encodeURI(str).replace( ...

  8. nyoj 过河问题

    过河问题 时间限制:1000 ms  |  内存限制:65535 KB 难度:5   描述 在漆黑的夜里,N位旅行者来到了一座狭窄而且没有护栏的桥边.如果不借助手电筒的话,大家是无论如何也不敢过桥去的 ...

  9. 易错点---所有的字符都自带bool值

    所有的字符都自带布尔值,只有0,None,空为False,其他全部为真!!!!!!!!!!! count = 0 while count < 3 : inp_age =input('Enter ...

  10. Apollo单向SSL认证(1)

    参考链接:https://www.cnblogs.com/benwu/articles/4891758.html keytool -genkey -alias mybroker -keyalg RSA ...