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-Team)

    第一天报告(10.25  周三) 团队:Java-Team 成员: 章辉宇(284) 吴政楠(286) 陈阳(PM:288) 韩华颂(142) 胡志权(143) github地址:https://gi ...

  2. 团队作业7——第二次项目冲刺(Beta版本12.10)

    项目每个成员的进展.存在问题.接下来两天的安排. 已完成的内容:头像功能原型设计.头像裁剪功能.头像上传功能.测试 计划完成的内容:头像功能测试.bug修复 每个人的工作 (有work item 的I ...

  3. djangoueditor 集成xadmin

    1.安装Python3兼容版本 https://github.com/twz915/DjangoUeditor3/ 2.model加入字段 from DjangoUeditor.models impo ...

  4. MySQL 自关联查询

    定义表areas,结构如下 id atitle pid 因为省没有所属的省份,所以可以填写为null 城市所属的省份pid,填写省所对应的编号id 这就是自关联,表中的某一列,关联了这个表中的另外一列 ...

  5. configparser 练习

    [kaixin]xxx = 333name = hahheh = 0[erick]age = 123555xxx = ooo555name = hah555 1 import configparser ...

  6. java 注解的实现机制

    一.什么是注解: 注解是标记,也可以理解成是一种应用在类.方法.参数.属性.构造器上的特殊修饰符.注解作用有以下三种: 第一种:生成文档,常用的有@param@return等. 第二种:替代配置文件的 ...

  7. JAVA_SE基础——31.this关键字

    黑马程序员入学blog... 也算是学习笔记体会. this的通俗解释: 有一个A类,一个B方法,一个C变量,其中B和C都在类A中 this.B()就是调用A类中的B方法 this.C=1(假设C是一 ...

  8. 在thinkphp框架中使用后台传值过来的数组,在hightcart中使用数组

    js的数组是和php里面数组是不一样的,所以模板文件需要先接受,然后利用Js代码转化之后再使用,接受后台的数组有几种办法 1.后台传过来的json数组,利用Js是可以接受的,然后将json数据利用js ...

  9. Docker学习笔记 - Docker Compose 脚本命令

    Docker Compose 配置文件包含 version.services.networks 三大部分,最关键的是 services 和 networks 两个部分, version: '2' se ...

  10. Spring Security入门(1-12)Spring Security 的过滤器机制

    Servlet过滤器被用来拦截用户请求来进行请求之前或之后的处理,或者干脆重定向这个请求,这取决于servlet过滤器的功能. Servlet过滤器处理之后的目标servlet是 MVC 分发web ...