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. Jenkins+Maven+SVN搭建自动部署、自动测试环境

    .打开http://10.3.15.78:8080/jenkins/,第一次进入里面没有数据,我们需要创建job,我们这有2个项目,需要创建2个job.http://10.3.34.163:9890/ ...

  2. Jquery源码中的Javascript基础知识(二)

    接上一篇,jquery源码的这种写法叫做匿名函数自执行 (function( window, undefined ) { // code })( window ); 函数定义了两个参数window和u ...

  3. web项目路径问题

    路径    相对路径        URL中第一个字符不为“/”        request.getRequestDispatcher("b");        相对于该代码所在 ...

  4. MKNetworkKit: 网络处理又一利器

    没有认识MK之前,即便ASI已经不再更新,也没有启用ASI.因为ASI对于网络的处理更偏向于底层,适合针对各种情形的扩展. 但是,今天我要开始使用 MKNetworkKit了,项目在github上,使 ...

  5. swun 1612 合并果子

      //思路:这题思路似乎很简单,每次取出最小的两个堆合并, //但是由于数据太大,不能采取每次进行排序的方式,所以 //想到用优先队列,以数据小的优先级更高为标准,但是 //优先队列中的数据默认情况 ...

  6. application tips

    trace(ApplicationDomain.currentDomain == ApplicationDomain.currentDomain); trace(stage.loaderInfo.ap ...

  7. linux 命令部分说明

    shell 文件头格式   #! /bin/sh 定义变量  dir_tmp=/tmp/xxx 级联创建 mkdir -p /etc/aaa/bbb 阻塞命令 等待用户输入回车  继续    read ...

  8. 【基础数学】质数,约数,分解质因数,GCD,LCM

    1.质数: 质数(prime number)又称素数,有无限个.一个大于1的自然数,除了1和它本身外,不能整除以其他自然数(质数),换句话说就是该数除了1和它本身以外不再有其他的因数. 2.约数: 如 ...

  9. 嵌入式 VFS: Cannot open root device "mtdblock2" or unknown-block(2,0)

    系统启动后,虽然nand驱动表现正常,但是最后挂载rootfs时候出错: Kernel command line: root=/dev/mtdblock2 rw init=/linuxrc conso ...

  10. DataGridView固定了列名,怎样将数据内容绑定在列上

    留心驿站 原文 其实很简单,在DataGridView上右键选择编辑列,在数据一项中找到DataPropertyName,在里面写上对应的要绑定的数据中的字段名,即可 .比如:从数据库中选择的data ...