hdu4670(树上点分治+状态压缩)
树上路径的f(u,v)=路径上所有点的乘积。
树上每个点的权值都是由给定的k个素数组合而成的,如果f(u,v)是立方数,那么就说明f(u,v)是可行的方案。
问有多少种可行的方案。
f(u,v)可是用状态压缩来表示,因为最多只有30个素数, 第i位表示第i个素数的幂,那么每一位的状态只有0,1,2因为3和0是等价的,所以用3进制状态来表示就行了。
其他代码就是裸的树分。
另外要注意的是,因为counts函数没有统计只有一个点的情况,所以需要另外统计。
#pragma warning(disable:4996)
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <math.h>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <vector>
#include <bitset>
#include <algorithm>
#include <iostream>
#include <string>
#include <functional>
#include <unordered_map>
const int INF = << ;
typedef __int64 LL;
/*
用三进制的每一位表示第i个素数的幂
如果幂都是0,那么说明是立方
*/
const int N = + ;
std::vector<int> g[N];
std::unordered_map<LL, int> mp;
struct Node
{
int sta[];
}node[N];
LL prime[];
std::vector<Node> dist;
int n, k;
int size[N], vis[N], total, root, mins;
LL _3bit[];
void init()
{
_3bit[] = ;
for (int i = ;i <= ;++i)
_3bit[i] = _3bit[i - ] * ;
}
void getRoot(int u, int fa)
{
int maxs = ;
size[u] = ;
for (int i = ;i < g[u].size();++i)
{
int v = g[u][i];
if (v == fa || vis[v]) continue;
getRoot(v, u);
size[u] += size[v];
maxs = std::max(maxs, size[v]);
}
maxs = std::max(maxs, total - size[u]);
if (mins > maxs)
{
mins = maxs;
root = u;
}
}
void getDis(int u, int fa, Node d)
{
dist.push_back(d);
for (int i = ;i < g[u].size();++i)
{
int v = g[u][i];
if (v == fa || vis[v]) continue;
Node tmp;
for (int j = ;j < k;++j)
tmp.sta[j] = (d.sta[j] + node[v].sta[j]) % ;
getDis(v, u, tmp);
}
}
LL counts(int u)//计算经过u点的路径
{
mp.clear();
mp[] = ;
LL ret = ;
for (int i = ;i < g[u].size();++i)
{
int v = g[u][i];
if (vis[v]) continue;
dist.clear();
getDis(v, u, node[v]);
for (int j = ;j < dist.size();++j)
{
LL sta = ;
for (int z = ;z < k;++z)
{
sta += ( - (node[u].sta[z] + dist[j].sta[z]) % ) % * _3bit[z];
}
ret += mp[sta];
}
for (int j = ;j < dist.size();++j)
{
LL sta = ;
for (int z = ;z < k;++z)
sta += dist[j].sta[z] * _3bit[z];
mp[sta]++;
}
}
return ret;
}
LL ans;
void go(int u)
{
vis[u] = true;
ans += counts(u);
for (int i = ;i < g[u].size(); ++i)
{
int v = g[u][i];
if (vis[v]) continue;
total = size[v];
mins = INF;
getRoot(v, u);
go(root);
} }
int main()
{
int u, v;
LL x;
init();
while (scanf("%d%d", &n, &k) != EOF)
{
for (int i = ;i < k;++i)
scanf("%I64d", &prime[i]);
ans = ;
for (int i = ;i <= n;++i)
{
g[i].clear();
vis[i] = ;
scanf("%I64d", &x);
memset(node[i].sta, , sizeof(node[i].sta));
int tmp = ;
for (int j = ;j <k;++j)
{ while (x%prime[j] == && x)
{
node[i].sta[j]++;
x /= prime[j];
}
node[i].sta[j] %= ;
if (node[i].sta[j] != )tmp++;
}
if (tmp == )//统计只有一个点的
ans++;
}
for (int i = ;i < n;++i)
{
scanf("%d%d", &u, &v);
g[u].push_back(v);
g[v].push_back(u);
}
total = n;
mins = INF;
getRoot(, -);
go(root);
printf("%I64d\n", ans);
}
return ;
}
hdu4670(树上点分治+状态压缩)的更多相关文章
- HDU 5977 Garden of Eden (树分治+状态压缩)
题意:给一棵节点数为n,节点种类为k的无根树,问其中有多少种不同的简单路径,可以满足路径上经过所有k种类型的点? 析:对于路径,就是两类,第一种情况,就是跨过根结点,第二种是不跨过根结点,分别讨论就好 ...
- topcoder-srm701-div2-900 博弈\计算二进制位1的个数\dp\状态压缩
借用一下qls翻译过来的题面 现在有 n 个石子,A 和 B 轮流取石子,A先,每次最多可以取 m 个石子,取到最后一个石子的人获胜,但是某个人如果取完石子时候剩余石子数的二进制表示中有奇数个1,这 ...
- POJ 3691 (AC自动机+状态压缩DP)
题目链接: http://poj.org/problem?id=3691 题目大意:给定N个致病DNA片段以及一个最终DNA片段.问最终DNA片段最少修改多少个字符,使得不包含任一致病DNA. 解题 ...
- hdu 4057(ac自动机+状态压缩dp)
题意:容易理解... 分析:题目中给的模式串的个数最多为10个,于是想到用状态压缩dp来做,它的状态范围为1-2^9,所以最大为2^10-1,那我们可以用:dp[i][j][k]表示长度为i,在tri ...
- POJ 2777.Count Color-线段树(区间染色+区间查询颜色数量二进制状态压缩)-若干年之前的一道题目。。。
Count Color Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 53312 Accepted: 16050 Des ...
- [BZOJ 4455] [ZJOI 2016] 小星星 (树形dp+容斥原理+状态压缩)
[BZOJ 4455] [ZJOI 2016] 小星星 (树形dp+容斥原理+状态压缩) 题面 给出一棵树和一个图,点数均为n,问有多少种方法把树的节点标号,使得对于树上的任意两个节点u,v,若树上u ...
- 状态压缩动态规划(状压DP)详解
0 引子 不要999,也不要888,只要288,只要288,状压DP带回家.你买不了上当,买不了欺骗.它可以当搜索,也可以卡常数,还可以装B,方式多样,随心搭配,自由多变,一定符合你的口味! 在计算机 ...
- POJ 3254. Corn Fields 状态压缩DP (入门级)
Corn Fields Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 9806 Accepted: 5185 Descr ...
- HDU 3605:Escape(最大流+状态压缩)
http://acm.hdu.edu.cn/showproblem.php?pid=3605 题意:有n个人要去到m个星球上,这n个人每个人对m个星球有一个选择,即愿不愿意去,"Y" ...
随机推荐
- RGB HSV HLS三种色彩模式转换(C语言实现)
Android项目上处理图像的代码(注释全部去掉) ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 ...
- Delphi Socket的最好项目——FastMsg IM(还有一些IM控件),RTC,RO,Sparkle等等,FileZilla Client/Server,wireshark,NSClient
https://www.nsclient.org/nsclient/ 好好学习,天天向上
- json转String 和 String转json 和判断对象类型
function ajaxGetMenuList(){ $.getJSON("login.do", function(json){ var r = ""; zN ...
- 第四章 Spring与JDBC的整合
这里选择的是mysql数据库. 4.1引入aop.tx的命名空间 为了事务配置的需要,我们引入aop.tx的命名空间 <?xml version="1.0" encoding ...
- javascript (二) 事件
<script></script> 函数写法: function fun_name(){ x=docment.getElementById("demo") ...
- 再谈JSON -json定义及数据类型
再谈json 近期在项目中使用到了highcharts ,highstock做了一些统计分析.使用jQuery ajax那就不得不使用json, 可是在使用过程中也出现了非常多的疑惑,比方说,什么情况 ...
- Android自己定义控件:老版优酷的三级菜单(效果图 + Demo)
效果图: 制作思路: 1.先分析这个效果,事实上能够理解为把三级菜单分成level1,level2,level3,level1是始终显示的. 点击level1后,level2会出现:点击level2后 ...
- MyCAT部署及实现读写分离(转)
MyCAT是mysql中间件,前身是阿里大名鼎鼎的Cobar,Cobar在开源了一段时间后,不了了之.于是MyCAT扛起了这面大旗,在大数据时代,其重要性愈发彰显.这篇文章主要是MyCAT的入门部署. ...
- 非对称加密RSA、Elgamal、背包算法、Rabin、D-H、ECC(椭圆曲线加密算法)等。使用最广泛的是RSA算法
非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey).公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密:如果用私 ...
- csdn android视频播放器开发
http://blog.csdn.net/column/details/myvideo.html