求树上点权积为立方数的路径数。

显然,分解质因数后,若所有的质因子出现的次数都%3==0,则该数是立方数。

于是在模意义下暴力统计即可。

当然,为了不MLE/TLE,我们不能存一个30长度的数组,而要压成一个long long。

存储状态用map即可,貌似哈希表可以随便卡掉……?

手动开栈……当然这样有可能MLE,所以还得改一些BFS……

<法一>map:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<map>
#include<queue>
using namespace std;
#define MAXN 50001
typedef pair<int,int> Point;
typedef long long ll;
struct Point2
{
int x;ll y;int z;
Point2(){}
Point2(const int &a,const ll &b,const int &c){x=a;y=b;z=c;}
};
#define MOD 50021
queue<Point2>q;
map<ll,int>ma;
int n,m,ans,ev[MAXN][31];
ll pr[MAXN];
int v[MAXN<<1],first[MAXN],next[MAXN<<1],en;
void AddEdge(const int &U,const int &V)
{
v[++en]=V;
next[en]=first[U];
first[U]=en;
}
bool centroid[MAXN];
int size[MAXN];
int calc_sizes(int U,int Fa)
{
int res=1;
for(int i=first[U];i;i=next[i])
if(v[i]!=Fa&&!centroid[v[i]])
res+=calc_sizes(v[i],U);
return size[U]=res;
}
Point calc_centroid(int U,int Fa,int nn)
{
Point res=make_pair(2147483647,-1);
int sum=1,maxv=0;
for(int i=first[U];i;i=next[i])
if(v[i]!=Fa&&!centroid[v[i]])
{
res=min(res,calc_centroid(v[i],U,nn));
maxv=max(maxv,size[v[i]]);
sum+=size[v[i]];
}
maxv=max(maxv,nn-sum);
res=min(res,make_pair(maxv,U));
return res;
}
int en2,en3;
ll td[MAXN],ds[MAXN],base[31];
void calc_dis(int U,int Fa)
{
td[en2]=0;
for(int j=1;j<=m;++j)
td[en2]+=ev[U][j]*base[j-1];
++ma[td[en2]];
q.push(Point2(U,td[en2++],Fa));
while(!q.empty())
{
Point2 Node=q.front(); q.pop();
for(int i=first[Node.x];i;i=next[i])
if(v[i]!=Node.z&&!centroid[v[i]])
{
ll t=Node.y;
td[en2]=0;
for(int j=1;j<=m;++j)
{
td[en2]+=((ev[v[i]][j]+t%3)%3)*base[j-1];
t/=3;
}
++ma[td[en2]];
q.push(Point2(v[i],td[en2++],Node.x));
}
}
}
int calc_pairs(ll dis[],int En,int S)
{
int res=0;
for(int i=0;i<En;++i)
{
ll che=0,t=dis[i];
for(int j=1;j<=m;++j)
{
che+=((6-t%3-ev[S][j])%3)*base[j-1];
t/=3;
}
res+=ma[che];
}
return res;
}
void solve(int U)
{
calc_sizes(U,-1);
int s=calc_centroid(U,-1,size[U]).second;
centroid[s]=1;
for(int i=first[s];i;i=next[i])
if(!centroid[v[i]])
solve(v[i]);
en3=0; ds[en3++]=0;
ma.clear();
for(int i=first[s];i;i=next[i])
if(!centroid[v[i]])
{
en2=0; calc_dis(v[i],s);
ans-=calc_pairs(td,en2,s);
memcpy(ds+en3,td,en2*sizeof(ll)); en3+=en2;
}
ans+=calc_pairs(ds,en3,s);
centroid[s]=0;
}
void init()
{
memset(first,0,(n+1)*sizeof(int));
memset(ev,0,sizeof(ev));
en=ans=0;
}
int main()
{
ll t; int a,b; base[0]=1;
for(int i=1;i<=30;++i) base[i]=base[i-1]*3;
while(scanf("%d%d",&n,&m)!=EOF)
{
init();
for(int i=1;i<=m;++i) scanf("%I64d",&pr[i]);
for(int i=1;i<=n;++i)
{
bool flag=1;
scanf("%I64d",&t);
for(int j=1;j<=m;++j)
{
while(t%pr[j]==0&&t)
{
++ev[i][j];
t/=pr[j];
}
ev[i][j]%=3;
if(ev[i][j]) flag=0;
}
ans+=flag;
}
for(int i=1;i<n;++i)
{
scanf("%d%d",&a,&b);
AddEdge(a,b);
AddEdge(b,a);
}
solve(1);
printf("%d\n",ans);
}
return 0;
}

Update:<法二>哈希表,新的姿势,超快的说

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
#define MAXN 50001
#define MOD 50021
typedef pair<int,int> Point;
typedef long long ll;
struct Point2
{
int x;ll y;int z;
Point2(){}
Point2(const int &a,const ll &b,const int &c){x=a;y=b;z=c;}
};
struct HashTable
{
ll v[MOD];
int en,first[MOD],next[MOD];
HashTable(){en=0;memset(first,-1,sizeof(first));}
void clear(){en=0;memset(first,-1,sizeof(first));}
void insert(const ll &V)
{
int U=(int)(V%MOD);
v[en]=V;
next[en]=first[U];
first[U]=en++;
}
int count(const ll &V)
{
int U=(int)(V%MOD),res=0;
for(int i=first[U];i!=-1;i=next[i])
if(v[i]==V)
++res;
return res;
}
}T;
queue<Point2>q;
int n,m,ans,ev[MAXN][31];
ll pr[MAXN];
int v[MAXN<<1],first[MAXN],next[MAXN<<1],en;
void AddEdge(const int &U,const int &V)
{
v[++en]=V;
next[en]=first[U];
first[U]=en;
}
bool centroid[MAXN];
int size[MAXN];
int calc_sizes(int U,int Fa)
{
int res=1;
for(int i=first[U];i;i=next[i])
if(v[i]!=Fa&&!centroid[v[i]])
res+=calc_sizes(v[i],U);
return size[U]=res;
}
Point calc_centroid(int U,int Fa,int nn)
{
Point res=make_pair(2147483647,-1);
int sum=1,maxv=0;
for(int i=first[U];i;i=next[i])
if(v[i]!=Fa&&!centroid[v[i]])
{
res=min(res,calc_centroid(v[i],U,nn));
maxv=max(maxv,size[v[i]]);
sum+=size[v[i]];
}
maxv=max(maxv,nn-sum);
res=min(res,make_pair(maxv,U));
return res;
}
int En,last;
ll dis[MAXN],base[31];
void calc_dis(int U,int Fa)
{
dis[En]=0;
for(int j=1;j<=m;++j)
dis[En]+=ev[U][j]*base[j-1];
q.push(Point2(U,dis[En++],Fa));
while(!q.empty())
{
Point2 Node=q.front(); q.pop();
for(int i=first[Node.x];i;i=next[i])
if(v[i]!=Node.z&&!centroid[v[i]])
{
ll t=Node.y;
dis[En]=0;
for(int j=1;j<=m;++j)
{
dis[En]+=((ev[v[i]][j]+t%3)%3)*base[j-1];
t/=3;
}
q.push(Point2(v[i],dis[En++],Node.x));
}
}
}
void calc_pairs(int s)
{
for(int i=last;i<En;++i)
{
ll che=0,t=dis[i];
for(int j=1;j<=m;++j)
{
che+=((6-t%3-ev[s][j])%3)*base[j-1];
t/=3;
}
ans+=T.count(che);
}
for(int i=last;i<En;++i) T.insert(dis[i]);
}
void solve(int U)
{
calc_sizes(U,-1);
int s=calc_centroid(U,-1,size[U]).second;
centroid[s]=1;
for(int i=first[s];i;i=next[i])
if(!centroid[v[i]])
solve(v[i]);
En=0; dis[En++]=0; T.insert(0);
for(int i=first[s];i;i=next[i])
if(!centroid[v[i]])
{
last=En;
calc_dis(v[i],s);
calc_pairs(s);
}
for(int i=0;i<En;++i) T.first[dis[i]%MOD]=-1;
T.en=0;
centroid[s]=0;
}
void init()
{
memset(first,0,(n+1)*sizeof(int));
memset(ev,0,sizeof(ev));
en=ans=0;
}
int main()
{
ll t; int a,b; base[0]=1;
for(int i=1;i<=30;++i) base[i]=base[i-1]*3;
while(scanf("%d%d",&n,&m)!=EOF)
{
init();
for(int i=1;i<=m;++i) scanf("%I64d",&pr[i]);
for(int i=1;i<=n;++i)
{
bool flag=1;
scanf("%I64d",&t);
for(int j=1;j<=m;++j)
{
while(t%pr[j]==0&&t)
{
++ev[i][j];
t/=pr[j];
}
ev[i][j]%=3;
if(ev[i][j]) flag=0;
}
ans+=flag;
}
for(int i=1;i<n;++i)
{
scanf("%d%d",&a,&b);
AddEdge(a,b);
AddEdge(b,a);
}
solve(1);
printf("%d\n",ans);
}
return 0;
}

<法三>哈希表,旧的姿势,比法一快,比法二慢

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
#define MAXN 50001
#define MOD 50021
typedef pair<int,int> Point;
typedef long long ll;
struct Point2
{
int x;ll y;int z;
Point2(){}
Point2(const int &a,const ll &b,const int &c){x=a;y=b;z=c;}
};
struct HashTable
{
ll v[MOD];
int en,first[MOD],next[MOD];
HashTable(){en=0;memset(first,-1,sizeof(first));}
void clear(){en=0;memset(first,-1,sizeof(first));}
void insert(const ll &V)
{
int U=(int)(V%MOD);
v[en]=V;
next[en]=first[U];
first[U]=en++;
}
int count(const ll &V)
{
int U=(int)(V%MOD),res=0;
for(int i=first[U];i!=-1;i=next[i])
if(v[i]==V)
++res;
return res;
}
}T;
queue<Point2>q;
int n,m,ans,ev[MAXN][31];
ll pr[MAXN];
int v[MAXN<<1],first[MAXN],next[MAXN<<1],en;
void AddEdge(const int &U,const int &V)
{
v[++en]=V;
next[en]=first[U];
first[U]=en;
}
bool centroid[MAXN];
int size[MAXN];
int calc_sizes(int U,int Fa)
{
int res=1;
for(int i=first[U];i;i=next[i])
if(v[i]!=Fa&&!centroid[v[i]])
res+=calc_sizes(v[i],U);
return size[U]=res;
}
Point calc_centroid(int U,int Fa,int nn)
{
Point res=make_pair(2147483647,-1);
int sum=1,maxv=0;
for(int i=first[U];i;i=next[i])
if(v[i]!=Fa&&!centroid[v[i]])
{
res=min(res,calc_centroid(v[i],U,nn));
maxv=max(maxv,size[v[i]]);
sum+=size[v[i]];
}
maxv=max(maxv,nn-sum);
res=min(res,make_pair(maxv,U));
return res;
}
int en2,en3;
ll td[MAXN],ds[MAXN],base[31];
void calc_dis(int U,int Fa)
{
td[en2]=0;
for(int j=1;j<=m;++j)
td[en2]+=ev[U][j]*base[j-1];
T.insert(td[en2]);
q.push(Point2(U,td[en2++],Fa));
while(!q.empty())
{
Point2 Node=q.front(); q.pop();
for(int i=first[Node.x];i;i=next[i])
if(v[i]!=Node.z&&!centroid[v[i]])
{
ll t=Node.y;
td[en2]=0;
for(int j=1;j<=m;++j)
{
td[en2]+=((ev[v[i]][j]+t%3)%3)*base[j-1];
t/=3;
}
T.insert(td[en2]);
q.push(Point2(v[i],td[en2++],Node.x));
}
}
}
int calc_pairs(ll dis[],int En,int S)
{
int res=0;
for(int i=0;i<En;++i)
{
ll che=0,t=dis[i];
for(int j=1;j<=m;++j)
{
che+=((6-t%3-ev[S][j])%3)*base[j-1];
t/=3;
}
res+=T.count(che);
}
return res;
}
void solve(int U)
{
calc_sizes(U,-1);
int s=calc_centroid(U,-1,size[U]).second;
centroid[s]=1;
for(int i=first[s];i;i=next[i])
if(!centroid[v[i]])
solve(v[i]);
en3=0; ds[en3++]=0;
T.clear();
for(int i=first[s];i;i=next[i])
if(!centroid[v[i]])
{
en2=0; calc_dis(v[i],s);
ans-=calc_pairs(td,en2,s);
memcpy(ds+en3,td,en2*sizeof(ll)); en3+=en2;
}
ans+=calc_pairs(ds,en3,s);
centroid[s]=0;
}
void init()
{
memset(first,0,(n+1)*sizeof(int));
memset(ev,0,sizeof(ev));
en=ans=0;
}
int main()
{
ll t; int a,b; base[0]=1;
for(int i=1;i<=30;++i) base[i]=base[i-1]*3;
while(scanf("%d%d",&n,&m)!=EOF)
{
init();
for(int i=1;i<=m;++i) scanf("%I64d",&pr[i]);
for(int i=1;i<=n;++i)
{
bool flag=1;
scanf("%I64d",&t);
for(int j=1;j<=m;++j)
{
while(t%pr[j]==0&&t)
{
++ev[i][j];
t/=pr[j];
}
ev[i][j]%=3;
if(ev[i][j]) flag=0;
}
ans+=flag;
}
for(int i=1;i<n;++i)
{
scanf("%d%d",&a,&b);
AddEdge(a,b);
AddEdge(b,a);
}
solve(1);
printf("%d\n",ans);
}
return 0;
}

【点分治】【map】【哈希表】hdu4670 Cube number on a tree的更多相关文章

  1. HDU4670 cube number on a tree(点分治+三进制加法)

    The country Tom living in is famous for traveling. Every year, many tourists from all over the world ...

  2. HDU4670 Cube number on a tree 树分治

    人生的第一道树分治,要是早点学我南京赛就不用那么挫了,树分治的思路其实很简单,就是对子树找到一个重心(Centroid),实现重心分解,然后递归的解决分开后的树的子问题,关键是合并,当要合并跨过重心的 ...

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

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

  4. 3.10 Go Map哈希表

    3.10 Go Map哈希表 map是key-value类型数据结构,读作(哈希表.字典),是一堆未排序的键值对集合. map是引用类型,使用make函数或者初始化表达式创建. map的key必须是支 ...

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

  6. HDU 4670 Cube number on a tree ( 树的点分治 )

    题意 : 给你一棵树 . 树的每一个结点都有一个权值 . 问你有多少条路径权值的乘积是一个全然立方数 . 题目中给了你 K 个素数 ( K <= 30 ) , 全部权值都能分解成这k个素数 思路 ...

  7. HDU 4670 Cube number on a tree

    divide and conquer on tree. #include <map> #include <vector> #include <cstdio> #in ...

  8. memcached哈希表操作主要逻辑笔记

    以下注释的源代码都在memcached项目的assoc.c文件中 /* how many powers of 2's worth of buckets we use */ unsigned int h ...

  9. [CareerCup] 13.2 Compare Hash Table and STL Map 比较哈希表和Map

    13.2 Compare and contrast a hash table and an STL map. How is a hash table implemented? If the numbe ...

随机推荐

  1. centos7上安装docker-ce社区版

    报错:Error: docker-ce-selinux conflicts with 2:container-selinux-2.12-2.gite7096ce.el7.noarch 转载:http: ...

  2. 使用Spring AOP实现读写分离(MySql实现主从复制)

    1.  背景 我们一般应用对数据库而言都是“读多写少”,也就说对数据库读取数据的压力比较大,有一个思路就是说采用数据库集群的方案,其中一个是主库,负责写入数据,我们称之为:写库: 其它都是从库,负责读 ...

  3. Jquery Ajax异步上传

    <script> $(function(){ $('#filephoto').change(function(imgFile){ console.log(imgFile) var file ...

  4. 【bzoj3196-二逼平衡树】线段树套平衡树

    http://acm.hust.edu.cn/vjudge/problem/42297 [题目描述] 写一种数据结构,来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名 2.查询区间 ...

  5. 【Foreign】冒泡排序 [暴力]

    冒泡排序 Time Limit: 10 Sec  Memory Limit: 256 MB Description Input Output 仅一行一个整数表示答案. Sample Input 4 5 ...

  6. MyBatis系列四 之 智能标签进行查询语句的拼接

    MyBatis系列四 之 智能标签进行查询语句的拼接 使用Foreach进行多条件查询 1.1 foreach使用数组进行多条件查询 在MyBatis的映射文件中进行如下配置 <!--根据数组进 ...

  7. bootstrap-datetimepicker年视图中endDate设置之后比正常时间提前两个月

    问题 bootstrap-datetimepicker年视图中endDate设置结束时间为2016-08,(即8月之后的日期不能选)而在日历上显示时为2016-06,相差两个月,即6月之后的日期不能选 ...

  8. ssh 免密码登录【用】

    ssh 无密码登录要使用公钥与私钥.linux下可以用用ssh-keygen生成公钥/私钥对,下面我以CentOS为例. 有机器A(192.168.1.155),B(192.168.1.181).现想 ...

  9. mpvue-小程序之蹲坑记

    1. 不支持 v-html 小程序里所有的 BOM/DOM 都不能用,也就是说 v-html 指令不能用 部分复杂的 JavaScript 渲染表达式 {{}} 双花括号的部分,直接编码到 wxml ...

  10. 【转】jmeter入门教程- Jmeter教程及技巧汇总

    https://blog.csdn.net/zouxiongqqq/article/details/72843500