题意:给定一棵树,求这个节点的所有子树中包括他本身与它互质的节点的个数.

解题思路:题利用dfs序+容斥原理+前缀和性质解决。题目中要求每个结点,和多少个它的子结点互素。如果每次为了求一个点去跑一遍dfs,复杂度将是 O(N(N+M))。一定会超时。因此需要深入加以分析。注意到n的范围是10^5以内的,因此可以事先用线性筛求出每个数含有哪些素因子。接下来,我们 尝试利用dfs序来求解。设num[i]表示遍历到当前结点时候,含有因数i(注意,不一定是素数)的结点个数。可以发现,如果第一次遍历到结点u,含有 u的因数的个数为a,那么第二次遍历到u时候,含有u的因数的个数变成了b,那么b-a就是u的子树中,含有u的因数的结点个数,即和u不互素的结点个 数。用总的结点数减掉这部分,即得到了和u互素的结点个数。这正是用了前缀和的性质。那么,如何求解有当前有多个结点含有u的因数呢?可以利用容斥原理求解。因为我们已经预处理出来了所有数的素因数,假设有len个素因数,由于“含 有”即表示只要有1个即可。因此结果就是{只含有1种素因子的个数}-{只含有2种素因子的个数}+{只含有3个素因子的个数}-...+ (-1)^(n-1){含有n个素因子的个数}。这恰好就是容斥原理。至此,问题得以解决。

 #include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<memory.h>
#include<cstdlib>
#include<vector>
#define clc(a,b) memset(a,b,sizeof(a))
#define LL long long int
using namespace std;
const int N=;
const double eps=1e-;
const int inf=0x3f3f3f3f; int n;
int val[N];
int ans[N];
int e;
int num[N];
int head[N];
vector<int>g[N];
struct Edge
{
int to,next;
}edge[N*]; void add(int u,int v)
{
edge[e].to=v;
edge[e].next=head[u];
head[u]=e++;
} void init()
{
for(int i=;i<N;i++)
{
if(!g[i].empty())
continue;
for(int j=i;j<N;j+=i)
g[j].push_back(i);
}
} int calc(int x,int y)//*y=0表示进入这颗树的时候,含有互质的数目为0;y=1表示dfs回溯的时候离开这棵树相应互质节点数目加一*//
{
int len=g[x].size();
int res=;
for(int i=;i<(<<len);i++)
{
int t=;
int cnt=;
for(int j=;j<len;j++)
{
if(i&(<<j))
{
cnt++;
t=t*g[x][j];
}
}
if(cnt%)
res+=num[t];
else
res-=num[t];
num[t]+=y;
}
return res;
}
int dfs(int u,int pre)
{
int cnt=;
int L=calc(val[u],);
for(int i=head[u];~i;i=edge[i].next)
{
int v=edge[i].to;
if(v==pre)
continue;
cnt+=dfs(v,u);
}
int R=calc(val[u],);
ans[u]=cnt-(R-L);
if(val[u]==)
ans[u]++;
return cnt+;
}
int main()
{
int u,v;
int cas=;
while(~scanf("%d",&n))
{
e=;
init();
clc(num,);
clc(head,-);
for(int i=;i<n-;i++)
{
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
for(int i=;i<=n;i++)
{
scanf("%d",&val[i]);
}
dfs(,);
printf("Case #%d:",cas++);
for(int i=;i<=n;i++)
{
printf(" %d",ans[i]);
}
printf("\n");
}
return ;
}

2015上海网络赛 A Puzzled Elena的更多相关文章

  1. hdu 5476 Explore Track of Point(2015上海网络赛)

    题目链接:hdu 5476 今天和队友们搞出3道水题后就一直卡在这儿了,唉,真惨啊……看着被一名一名地挤出晋级名次,确实很不好受,这道恶心的几何题被我们3个搞了3.4个小时,我想到一半时发现样例输出是 ...

  2. 2015上海网络赛 HDU 5478 Can you find it 数学

    HDU 5478 Can you find it 题意略. 思路:先求出n = 1 时候满足条件的(a,b), 最多只有20W对,然后对每一对进行循环节判断即可 #include <iostre ...

  3. 2015上海网络赛 HDU 5475 An easy problem 线段树

    题意就不说了 思路:线段树,维护区间乘积.2操作就将要除的点更新为1. #include<iostream> #include<cstdio> #include<cstr ...

  4. 2015北京网络赛 D-The Celebration of Rabbits 动归+FWT

    2015北京网络赛 D-The Celebration of Rabbits 题意: 给定四个正整数n, m, L, R (1≤n,m,L,R≤1000). 设a为一个长度为2n+1的序列. 设f(x ...

  5. 2015北京网络赛 J Scores bitset+分块

    2015北京网络赛 J Scores 题意:50000组5维数据,50000个询问,问有多少组每一维都不大于询问的数据 思路:赛时没有思路,后来看解题报告也因为智商太低看了半天看不懂.bitset之前 ...

  6. 2015北京网络赛 Couple Trees 倍增算法

    2015北京网络赛 Couple Trees 题意:两棵树,求不同树上两个节点的最近公共祖先 思路:比赛时看过的队伍不是很多,没有仔细想.今天补题才发现有个 倍增算法,自己竟然不知道.  解法来自 q ...

  7. 2015长春网络赛1001 求连通快数量的问题dfs

    Ponds Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Sub ...

  8. Hiho coder 1236 2015 北京网络赛 Score

    五维偏序..一开始被吓到了,后来知道了一种BITSET分块的方法,感觉非常不错. 呆马: #include <iostream> #include <cstdio> #incl ...

  9. HDU 5044(2014 ACM-ICPC上海网络赛)

    题意:给定一个树形图,节点10^5,有两种操作,一种是把某两点间路径(路径必定唯一)上所有点的权值增加一个固定值. 另一种也是相同操作,不同的是给边加权值.操作次数10^5.求操作过后,每个点和每条边 ...

随机推荐

  1. JAVA CAS单点登录(SSO) 教程

    一.教程前言 教程目的:从头到尾细细道来单点登录服务器及客户端应用的每个步骤 单点登录(SSO):请看百科解释猛击这里打开 本教程使用的SSO服务器是Yelu大学研发的CAS(Central Auth ...

  2. QueryPerformanceFrequency 和 QueryPerformanceCounter用法

    QueryPerformanceFrequency() - 基本介绍 类型:Win32API 原型:BOOL QueryPerformanceFrequency(LARGE_INTEGER *lpFr ...

  3. POJ2524+并查集

    题意简单. 询问n个人的宗教关系. #include<stdio.h> ; int fa[ maxn ]; int vis[ maxn ]; void init( int n ){ ;i& ...

  4. SQLite入门与分析(二)---设计与概念

    写在前面:谢谢各位的关注,没想到会有这么多人关注.高兴的同时,也感到压力,因为我接触SQLite也就几天,也没在实际开发中用过,只是最近项目的需求才来研究它,所以我很担心自己的文章是否会有错误,误导别 ...

  5. POJ3083——Children of the Candy Corn(DFS+BFS)

    Children of the Candy Corn DescriptionThe cornfield maze is a popular Halloween treat. Visitors are ...

  6. 隐马尔科夫模型,第三种问题解法,维比特算法(biterbi) algorithm python代码

    上篇介绍了隐马尔科夫模型 本文给出关于问题3解决方法,并给出一个例子的python代码 回顾上文,问题3是什么, 下面给出,维比特算法(biterbi) algorithm 下面通过一个具体例子,来说 ...

  7. nyist 510昂贵的聘礼

    /* 好好的图论题啊,最短路的应用,dijkstra算法 */ #include <iostream> using namespace std; const int INF=100000; ...

  8. redolog 大小的实验

    前言:近日因工作需要,测试postgresql和MySQL在oltp对比测试,因结果差异太多(MySQL测试结果比较差,相同环境),寻求大神帮助,有幸得叶大师和姜大师指点,指出my.cnf配置文件in ...

  9. 摄像头(4)用Camera和SurfaceView自定义拍照程序

    定制拍照程序的基本步骤 1,打开照相机:Camera.open 这是独占方式打开的 2,创建SurfaceView对象 多缓冲,多线程view 3,添加回调事件监听器(SurfaceHolder.ad ...

  10. Java之跳出多重循环

    在java里,想要跳出多重循环,有两种方法 1.在循环语句前设置一个标记,然后使用带有该标记的break语句跳出该循环 public static void main(String args[]) { ...