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/Others)
Total Submission(s): 1628 Accepted Submission(s): 382
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.
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.
3 2 3 5
2500 200 9 270000 27
4 2
3 5
2 5
4 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(点分治)的更多相关文章
- HDU 4670 Cube number on a tree
divide and conquer on tree. #include <map> #include <vector> #include <cstdio> #in ...
- HDU 4670 Cube number on a tree ( 树的点分治 )
题意 : 给你一棵树 . 树的每一个结点都有一个权值 . 问你有多少条路径权值的乘积是一个全然立方数 . 题目中给了你 K 个素数 ( K <= 30 ) , 全部权值都能分解成这k个素数 思路 ...
- HDU4670 cube number on a tree(点分治+三进制加法)
The country Tom living in is famous for traveling. Every year, many tourists from all over the world ...
- 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 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 ...
- hdu 2665 Kth number
划分树 /* HDU 2665 Kth number 划分树 */ #include<stdio.h> #include<iostream> #include<strin ...
- HDU - 3584 Cube (三维树状数组 + 区间改动 + 单点求值)
HDU - 3584 Cube Time Limit: 1000MS Memory Limit: 65536KB 64bit IO Format: %I64d & %I64u Subm ...
随机推荐
- python 继承基础
class annamal: def chi(self): print(self.name + '吃') def he(self): print(self.name + '喝') class dog( ...
- 申请JetBrains学生免费注册码
1.申请.edu.*后缀的邮箱 从某个知乎用户上面得到了两个可以申请的后缀edu的邮箱 上海交通大学校友统一身份认证:https://register.alumni.sjtu.edu.cn/alumn ...
- Node入门教程(4)第三章:第一个 Nodejs 程序
第一个 Nodejs 程序 本教程仅适合您已经有一定的JS编程的基础或者是后端语言开发的基础.如果您是零基础,建议您先学一下老马的前端免费视频教程 第一步:创建项目文件夹 首先创建 demos 文件夹 ...
- PCB名詞解釋:通孔、盲孔、埋孔(转载)
文章转载自:https://www.researchmfg.com/2011/07/pth-blind-hole-buried-hole/ PCB名詞解釋:通孔.盲孔.埋孔 Posted by 工作熊 ...
- Python基础学习篇章三
一. Python对象类型 1. 对象是Python最基本的概念,一个Python程序可以分解为模块.语句.表达式.和对象.它们的关系如下:(1)程序由模块构成 (2)模块包含语句 (3)语句包含表达 ...
- emqtt 试用(七)追踪
追踪 EMQ 消息服务器支持追踪来自某个客户端(Client)的全部报文,或者发布到某个主题(Topic)的全部消息. 追踪客户端(Client): ./bin/emqttd_ctl trace cl ...
- Linux--慕课学习
刚开始接触Linux,很有幸的在慕课网上看到了Peter老师的Linux入门课程,老师讲课真的式行云流水,深入浅出,循循善诱,层层递进. 老师分享的都是自己多年来总结的经验.看完之后也学到了很多东西. ...
- Excel 日期截取(函数)
需求:时间段截取,去掉年月日,保留时分. 实现函数: =TEXT(A2,"HH:MM")&"-"&TEXT(B2,"HH:MM& ...
- linux下查看mysql日志文件的方法
查看mysql日志方法: mysql默认不允许我们查看日志.需要更改一些设置 1 vi 更改配置文件 允许用户查看日志文件 sudo vi /etc/mysql/mysql.conf.d/mysqld ...
- mysql中text数据类型
有个小问题记录下: 需要从第三方api接口获取数据,返回的数据的长度不定,设计表的时候设计成了varchar(256):结果存数据的时候提示表字段长度不够. 一直从300改到500,600,700都一 ...