树上路径的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(树上点分治+状态压缩)的更多相关文章

  1. HDU 5977 Garden of Eden (树分治+状态压缩)

    题意:给一棵节点数为n,节点种类为k的无根树,问其中有多少种不同的简单路径,可以满足路径上经过所有k种类型的点? 析:对于路径,就是两类,第一种情况,就是跨过根结点,第二种是不跨过根结点,分别讨论就好 ...

  2. topcoder-srm701-div2-900 博弈\计算二进制位1的个数\dp\状态压缩

    借用一下qls翻译过来的题面  现在有 n 个石子,A 和 B 轮流取石子,A先,每次最多可以取 m 个石子,取到最后一个石子的人获胜,但是某个人如果取完石子时候剩余石子数的二进制表示中有奇数个1,这 ...

  3. POJ 3691 (AC自动机+状态压缩DP)

    题目链接:  http://poj.org/problem?id=3691 题目大意:给定N个致病DNA片段以及一个最终DNA片段.问最终DNA片段最少修改多少个字符,使得不包含任一致病DNA. 解题 ...

  4. hdu 4057(ac自动机+状态压缩dp)

    题意:容易理解... 分析:题目中给的模式串的个数最多为10个,于是想到用状态压缩dp来做,它的状态范围为1-2^9,所以最大为2^10-1,那我们可以用:dp[i][j][k]表示长度为i,在tri ...

  5. POJ 2777.Count Color-线段树(区间染色+区间查询颜色数量二进制状态压缩)-若干年之前的一道题目。。。

    Count Color Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 53312   Accepted: 16050 Des ...

  6. [BZOJ 4455] [ZJOI 2016] 小星星 (树形dp+容斥原理+状态压缩)

    [BZOJ 4455] [ZJOI 2016] 小星星 (树形dp+容斥原理+状态压缩) 题面 给出一棵树和一个图,点数均为n,问有多少种方法把树的节点标号,使得对于树上的任意两个节点u,v,若树上u ...

  7. 状态压缩动态规划(状压DP)详解

    0 引子 不要999,也不要888,只要288,只要288,状压DP带回家.你买不了上当,买不了欺骗.它可以当搜索,也可以卡常数,还可以装B,方式多样,随心搭配,自由多变,一定符合你的口味! 在计算机 ...

  8. POJ 3254. Corn Fields 状态压缩DP (入门级)

    Corn Fields Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 9806   Accepted: 5185 Descr ...

  9. HDU 3605:Escape(最大流+状态压缩)

    http://acm.hdu.edu.cn/showproblem.php?pid=3605 题意:有n个人要去到m个星球上,这n个人每个人对m个星球有一个选择,即愿不愿意去,"Y" ...

随机推荐

  1. 新建表维护程序SM30

    1.先新建一个客制表 2.创建一个函数组 3.SE11中该表->实用程序->表维护生成器->权限组填写&NC& ->  函数组填写刚才创建的函数组->维护 ...

  2. memcached vs MySQL Memory engine table 速度比较_XMPP Jabber即时通讯开发实践_百度空间

    memcached vs MySQL Memory engine table 速度比较_XMPP Jabber即时通讯开发实践_百度空间 memcached vs MySQL Memory engin ...

  3. SQL查询数据封装JavaBean对象

    public static List getListBySql(String sql, Class cls){   List list = new ArrayList();   Connection ...

  4. Python爬行动物(一):基本概念

    定义网络爬虫          网络爬虫(Web Spider,也被称为网络蜘蛛,网络机器人,也被称为网页追逐者).按照一定的规则,维网信息的程序或者脚本.另外一些不常使用的名字还有蚂蚁,自己主动索引 ...

  5. 高效 Java Web 开发框架 JessMA v3.2.3 beta-1 发布

    JessMA(原名:Portal-Basic)是一套功能完备的高性能 Full-Stack Web 应用开发框架,内置可扩展的 MVC Web 基础架构和 DAO 数据库访问组件(内部已提供了 Hib ...

  6. 无锁队列--基于linuxkfifo实现

    一直想写一个无锁队列,为了提高项目的背景效率. 有机会看到linux核心kfifo.h 原则. 所以这个实现自己仿照,眼下linux我们应该能够提供外部接口. #ifndef _NO_LOCK_QUE ...

  7. 使用ffmpeg 对视频截图,和视频转换格式

    //执行CMD命令方法 public static void CmdProcess(string command)//调用CMD        {            //实例化一个进程类      ...

  8. PHP网站安装程序的原理及代码

    原文:PHP网站安装程序的原理及代码 原理: 其实PHP程序的安装原理无非就是将数据库结构和内容导入到相应的数据库中,从这个过程中重新配置连接数据库的参数和文件,为了保证不被别人恶意使用安装文件,当安 ...

  9. [Android学习笔记]ShareSDK的使用

    ShareSDK使用方便,集成简单,正式客户端开发人员的首选组件 集成步骤,使用说明见官方文档: http://wiki.sharesdk.cn/Android_快速集成指南 记录: 直接使用官方De ...

  10. J2EE 13规范(4)-JSP

    JSP全称(Java Server Page ),也称javaserver页面.看到jsp是否立马想到原先以前学过的asp呢. 一.jsp和asp的比較: JSP(Java Server Page)与 ...