divide and conquer on tree.

#include <map>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
using namespace std;
const int N = 5e4+10;
const int K = 32;
typedef long long LL; struct edge_t {
int v, to;
};
vector<edge_t> E;
int L[N];
void init(int n) {
E.clear();
memset(L, -1, sizeof(int)*n);
}
void add_edge(int u, int v) {
edge_t t = {v, L[u]};
L[u] = E.size();
E.push_back(t);
} int n, k;
LL w[N], p[K]; LL ll_split(LL x) {
LL rv = 0;
for (int i = 0; i < k; i++) {
LL o = 0;
for ( ; x%p[i] == 0; x/= p[i]) o++;
rv |= o%3<<(i<<1);
}
return rv;
}
LL ll_add(LL lhs, LL rhs) {
LL rv = 0;
for (int i = 0; i < k; i++) {
LL o = ((lhs>>(i<<1)&3)+(rhs>>(i<<1)&3))%3;
rv |= o<<(i<<1);
}
return rv;
}
LL ll_com(LL x) {
LL rv = 0;
for (int i = 0; i < k; i++) {
rv |= (3-(x>>(i<<1)&3))%3<<(i<<1);
}
return rv;
}
void ll_show(LL x) {
for (int i = 0; i < k; i++) {
printf("%lld ", x>>(i<<1)&3);
}
} bool vis[N];
int size, s[N];
void get_size(int u) {
vis[u] = 1;
s[u] = 1;
for (int i = L[u]; ~i; i = E[i].to) {
int v = E[i].v;
if (vis[v]) continue;
get_size(v);
s[u] += s[v];
}
vis[u] = 0;
}
int core;
void find_core(int u) {
vis[u] = 1;
int flag = 1;
for (int i = L[u]; ~i; i = E[i].to) {
int v = E[i].v;
if (vis[v]) continue;
if (s[v] > size/2) flag = 0;
find_core(v);
}
if (flag && size-s[u] <= size/2) core = u;
vis[u] = 0;
}
vector<LL> dis;
void get_dis(int u, LL d) {
vis[u] = 1;
dis.push_back(ll_add(w[u], d));
for (int i = L[u]; ~i; i = E[i].to) {
int v = E[i].v;
if (vis[v]) continue;
get_dis(v, ll_add(w[u], d));
}
vis[u] = 0;
}
int dac(int u) {
get_size(u);
size = s[u];
if (size == 1) return !w[u];
find_core(u);
int rv = !w[u = core];
vis[u] = 1;
map<LL, int> m;
m[0]++;
for (int i = L[u]; ~i; i = E[i].to) {
int v = E[i].v;
if (vis[v]) continue;
dis.clear();
get_dis(v, 0);
for (int j = 0; j < dis.size(); j++) {
map<LL, int>::iterator it = m.find(ll_com(ll_add(dis[j], w[u])));
if (it != m.end()) rv += it->second;
}
for (int j = 0; j < dis.size(); j++) m[dis[j]]++;
}
for (int i = L[u]; ~i; i = E[i].to) {
int v = E[i].v;
if (vis[v]) continue;
rv += dac(v);
}
vis[u] = 0;
return rv;
} int main() {
for ( ; ~scanf("%d", &n); ) {
init(n);
scanf("%d", &k);
for (int i = 0; i < k; i++) {
char b[32];
scanf("%s", b);
p[i] = atoll(b);
}
for (int i = 0; i < n; i++) {
char b[32];
scanf("%s", b);
w[i] = ll_split(atoll(b));
}
for (int i = 0; i < n-1; i++) {
int u, v;
scanf("%d%d", &u, &v);
u--, v--;
add_edge(u, v);
add_edge(v, u);
}
printf("%d\n", dac(0));
}
return 0;
}

HDU 4670 Cube number on a tree的更多相关文章

  1. 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/ ...

  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. 【点分治】【map】【哈希表】hdu4670 Cube number on a tree

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

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

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

  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. makeObjectsPerformSelector: 方法的用法

    //让数组中得每个元素都调用 @selector 中的get方法 [self.buttons makeObjectsPerformSelector:@selector(get)]; NSString ...

  2. C# 创建系统服务并定时执行【转载】

    [转载]http://www.cnblogs.com/hfzsjz/archive/2011/01/07/1929898.html C# 创建系统服务并定时执行 1.新建项目 --> Windo ...

  3. ORACLE 分区

    在建设数据仓库过程中,经常会有大量数据,短时间内表中数据量有限,查询性能还可以,但随着时间的延长,表中数据量迅速增加,查询速度就会变慢,性能下降,这时就要考虑对表进行分区. 一.oracle的分区 当 ...

  4. python开发学习-day01 (python安装与版本、字符串、字典、运算符、文件)

    *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...

  5. TextView及其子类

    1.TextView控件(TextView是EditView.Button等类的父类) <1>android:id   给当前控件定义了一个唯一标识符 <2>android:l ...

  6. 下载个jquery-easyui-1.3.0使用,把他导入到myeclipse10里,jquery-1.7.2.min.js报错。 错误如下, Syntax error on token "Invalid Regular Expression Options", no accurate correc

    1.选中报错的jquery文件“jquery-1.2.6.min.js”.2.右键选择 MyEclipse-->Exclude From Validation .3.再右键选择 MyEclips ...

  7. 删除特定影响因素(字段列)下的重复记录(MySQL)

    ;CREATE TABLE TabTest ( `id` ) NOT NULL AUTO_INCREMENT ,`factorA` ) NOT NULL DEFAULT ' ' ,`factorB` ...

  8. [再寄小读者之数学篇](2014-11-19 $\sin(x+y)=\sin x\cos y+\cos x\sin y$)

    $$\bex \sin(x+y)=\sin x\cos y+\cos x\sin y. \eex$$ Ref. [Proof Without Words: Sine Sum Identity, The ...

  9. struts2异常处理,global-results定义全局结果处理

    <global-results>定义全局结果处理 一般发生异常之后 结果返回errHandler 因为errHandler是由<global-exception-mappings&g ...

  10. Groovy读取properties及txt

    昨晚帮老同事解决了一个SoapUI的代码问题,好长时间没用SoapUI,好多东西都忘了,今天先总结下Groovy读取properties 首先吐槽下SoapUI的apidocs,我几乎从中看不出什么东 ...