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. JAVA接口基础知识总结

    1:是用关键字interface定义的. 2:接口中包含的成员,最常见的有全局常量.抽象方法. 注意:接口中的成员都有固定的修饰符. 成员变量:public static final     成员方法 ...

  2. codeforces 830 B Cards Sorting

    B. Cards Sorting  http://codeforces.com/problemset/problem/830/B Vasily has a deck of cards consisti ...

  3. Vim 游戏 2048

    给大家介绍一款可以在Vim里面玩的游戏 vim2048. 界面如图: 操作非常简单,可以用 hjkl 或者 上下左右方向键移动 项目开源地址为: https://github.com/wsdjeg/v ...

  4. System.Reflection名称空间下的程序集类Assembly应用.

    利用反射中的程序集类(Assembly--抽象类)动态加载类库(.dll)或者可执行程序(.exe). 优点:①.可以消除if条件的逻辑判断.②.减少内存资源.③.有利于程序扩展. 缺点... 使用静 ...

  5. xftp上传文件失败,执行程序发现磁盘满了:No space left on device

    参考链接 No space left on device 解决Linux系统磁盘空间满的办法http://www.cnblogs.com/aspirant/p/3604801.html如何解决linu ...

  6. 新概念英语(1-125)Tea for two

    Does Susan have tea by herself?A:Can't you come in and have tea now,Peter? Not yet.B:I must water th ...

  7. Vue全家桶

    简介 “简单却不失优雅,小巧而不乏大匠”. Vue.js 是一个JavaScriptMVVM库,是一套构建用户界面的渐进式框架.它是以数据驱动和组件化的思想构建的,采用自底向上增量开发的设计. 为什么 ...

  8. 记一次将公司网站http换成https

    看了博客园将近一年了,一直都只是在被动的看,总觉得应该写点什么,但是又不知道该写点什么.今天正好公司要把网站由http换成https,那我就顺便记录一下吧. 由于之前没有弄过,所以就面向百度编程. 首 ...

  9. Android:ImageView控件显示图片

    1)android显示图片可以使用imageView来呈现,而且也可以通过ImageButton来实现给button添加图片. 2)在创建一个ImageView后,显示图片绑定元素是:android: ...

  10. 初识 SpringMVC

    1.Spring MVC 的工作流程 1.web请求被 前端控制器(DispatcherServlet)拦截 2.DispatcherServlet调用 映射处理器(HandelerMapping)查 ...