【点分治】【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 ...
随机推荐
- jQuery通过CSS()方法给指定的元素同时设置多个样式
<!DOCTYPE html> <html> <head> <script src="http://ajax.googleapis.com/ajax ...
- 【数据结构】bzoj1651专用牛棚
Description Oh those picky N (1 <= N <= 50,000) cows! They are so picky that each one will onl ...
- 【BZOJ1419】 Red is good [期望DP]
Red is good Time Limit: 10 Sec Memory Limit: 64 MB[Submit][Status][Discuss] Description 桌面上有R张红牌和B张 ...
- 【BZOJ】1571: [Usaco2009 Open]滑雪课Ski
[算法]动态规划 [题解]yy出了O(1w log 1w)的算法. 将雪坡排序预处理出g[i]表示能力值为i的最短时长雪坡. 这样就可以定义work(t,c)表示时长t能力c的最多滑雪数量,work( ...
- DotNETCore 学习笔记 异常处理
Error Handling public void Configure(IApplicationBuilder app, IHostingEnvironment env) { app.UseIISP ...
- Django-随机验证码
Python生成随机验证码,需要使用PIL模块. 安装: 1 pip3 install pillow 基本使用 1. 创建图片 from PIL import Image img = Image.ne ...
- linux下源码安装netcat
linux下源码安装netcat http://blog.chinaunix.net/uid-20783755-id-4211230.html 1,下载netcat源码,netcat-0.7.1-13 ...
- spring注解导入配置文件
@Configuration @ImportResource("classpath:config.xml") public class StoreConfig { @Value(& ...
- 使用WindowManager添加View——悬浮窗口的基本原理
Android系统中的“窗口”类型虽然很多,但只有两大类是经常使用的:一是由系统进程管理的,称之为“系统窗口”:第二个就是由应用程序产生的,用于显示UI界面的“应用窗口”.如果大家熟悉WindowMa ...
- JSP 基础之 JSTL <c:choose>用法 if else
<c:choose> <c:when test="${condition1}"> condition1为true </c:when> <c ...