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

显然,分解质因数后,若所有的质因子出现的次数都%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;
}

最新文章

  1. Java中Unicode的编码和实现
  2. C#:简单线程样例
  3. UVa 1592 数据库(c++pair)
  4. 【S16】了解如何把vector和string数据传给旧的API
  5. React-Native学习指南
  6. WPF2D绘制图形方法
  7. J - 今年暑假不AC
  8. Java泛型学习笔记--Java泛型和C#泛型比较学习(一)
  9. Box2d FilterData
  10. 计算机学院大学生程序设计竞赛(2015’12) 1003 The collector’s puzzle
  11. eNSP仿真学习,网络入门!
  12. 搭建DNS服务
  13. 【Hdu3555】 Bomb(数位DP)
  14. win下开机不登陆系统自动运行程序的解决方案
  15. Angular $broadcast和$emit和$ond实现父子通信
  16. Eclipse+Maven创建webapp项目&lt;二&gt;
  17. Day1-Request/BeautifulSoup
  18. 关于SQLSERVER走起公众帐号推送视频的通知
  19. 【linux】环境变量
  20. 格式化字符串漏洞利用实战之 0ctf-easyprintf

热门文章

  1. innodb log file与binlog的区别在哪里?
  2. C语言一些常用的功能
  3. Python代码规范
  4. sencha touch 模仿tabpanel导航栏TabBar的实现代码
  5. BZoj 1003 物流运输 DP+最短路
  6. bzoj 2115 路径xor和最大值
  7. Apache服务器
  8. glib windows下编译
  9. 搜索引擎--范例:SAE创建新应用,SVN管理代码
  10. mysql绿色版配置