【点分治】【map】【哈希表】hdu4670 Cube number on a tree
求树上点权积为立方数的路径数。
显然,分解质因数后,若所有的质因子出现的次数都%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的更多相关文章
- HDU4670 cube number on a tree(点分治+三进制加法)
The country Tom living in is famous for traveling. Every year, many tourists from all over the world ...
- HDU4670 Cube number on a tree 树分治
人生的第一道树分治,要是早点学我南京赛就不用那么挫了,树分治的思路其实很简单,就是对子树找到一个重心(Centroid),实现重心分解,然后递归的解决分开后的树的子问题,关键是合并,当要合并跨过重心的 ...
- [hdu4670 Cube number on a tree]点分治
题意:给一个N个带权节点的树,权值以给定的K个素数为因子,求路径上节点乘积为立方数的路径条数 思路:立方数的性质是每个因子的个数为3的倍数,那么每个因子只需要保存0-2三个状态即可,然后路径就可以转化 ...
- 3.10 Go Map哈希表
3.10 Go Map哈希表 map是key-value类型数据结构,读作(哈希表.字典),是一堆未排序的键值对集合. map是引用类型,使用make函数或者初始化表达式创建. map的key必须是支 ...
- 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/ ...
- HDU 4670 Cube number on a tree ( 树的点分治 )
题意 : 给你一棵树 . 树的每一个结点都有一个权值 . 问你有多少条路径权值的乘积是一个全然立方数 . 题目中给了你 K 个素数 ( K <= 30 ) , 全部权值都能分解成这k个素数 思路 ...
- HDU 4670 Cube number on a tree
divide and conquer on tree. #include <map> #include <vector> #include <cstdio> #in ...
- memcached哈希表操作主要逻辑笔记
以下注释的源代码都在memcached项目的assoc.c文件中 /* how many powers of 2's worth of buckets we use */ unsigned int h ...
- [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 ...
随机推荐
- 运动目标前景检测之ViBe源代码分析
一方面为了学习,一方面按照老师和项目的要求接触到了前景提取的相关知识,具体的方法有很多,帧差.背景减除(GMM.CodeBook. SOBS. SACON. VIBE. W4.多帧平均……).光流(稀 ...
- spring中<bean>中parent标签的使用
简介:spring 中parent标签是指:某个<bean>的父类.这个类可以覆盖parent的属性, 代码如下: Parent类的代码如下: package com.timo.domai ...
- Kafka自我学习-报错篇
1. kafka启动出现:Unsupported major.minor version 52.0 错误, 具体的错误输出: Exception in thread "main" ...
- TypeScript+Vue初体验Demo
github: https://github.com/lanleilin/Typescript-Vue-Demo
- js获取当前url地址参数中文乱码问题
网上看了一些关于此问题的文章,都说的不清不楚,有些更是乱七八糟,完全没法看,故此找了一篇能用的,借鉴作为笔记. //首先获取到当前页面的地址栏信息 var url = window.location. ...
- .NET的PE文件结构篇(转)
一.开篇 开篇我要讲述一个关于PE文件结构的文章,这篇文章动手能力比较强,希望大家能够动手进行操作,这边文章篇幅有可能会长一些,为了方便大家阅读我可以将其分为几个部分进行讲解,主要分为以下几个部分: ...
- RPC-整体概念
RPC概述 RPC(Remote Procedure Call),即远程过程调用,是一种通过网络从远程计算机程序上请求服务而不需要了解底层网络技术的协议,实现调用远程主机上的方法就像调用本地方法一样. ...
- HDOJ 3501 Calculation 2
题目链接 分析: 要求的是小于$n$的和$n$不互质的数字之和...那么我们先求出和$n$互质的数字之和,然后减一减就好了... $\sum _{i=1}^{n} i[gcd(i,n)==1]=\le ...
- codefoeces problem 671D——贪心+启发式合并+平衡树
D. Roads in Yusland Mayor of Yusland just won the lottery and decided to spent money on something go ...
- codeforce C. Okabe and Boxes
题目传送门 这道题 每次删除一个点 那么这个点必然在栈里面 那么如果堆顶不是他 我们就需要一次操作使得堆合理 这时我们可以把他删除然后把他下面的点打个标记表示这下面的点以后想怎么排就怎么排以后都不需要 ...