2015上海网络赛 A Puzzled Elena
题意:给定一棵树,求这个节点的所有子树中包括他本身与它互质的节点的个数.
解题思路:题利用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的更多相关文章
- hdu 5476 Explore Track of Point(2015上海网络赛)
题目链接:hdu 5476 今天和队友们搞出3道水题后就一直卡在这儿了,唉,真惨啊……看着被一名一名地挤出晋级名次,确实很不好受,这道恶心的几何题被我们3个搞了3.4个小时,我想到一半时发现样例输出是 ...
- 2015上海网络赛 HDU 5478 Can you find it 数学
HDU 5478 Can you find it 题意略. 思路:先求出n = 1 时候满足条件的(a,b), 最多只有20W对,然后对每一对进行循环节判断即可 #include <iostre ...
- 2015上海网络赛 HDU 5475 An easy problem 线段树
题意就不说了 思路:线段树,维护区间乘积.2操作就将要除的点更新为1. #include<iostream> #include<cstdio> #include<cstr ...
- 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 ...
- 2015北京网络赛 J Scores bitset+分块
2015北京网络赛 J Scores 题意:50000组5维数据,50000个询问,问有多少组每一维都不大于询问的数据 思路:赛时没有思路,后来看解题报告也因为智商太低看了半天看不懂.bitset之前 ...
- 2015北京网络赛 Couple Trees 倍增算法
2015北京网络赛 Couple Trees 题意:两棵树,求不同树上两个节点的最近公共祖先 思路:比赛时看过的队伍不是很多,没有仔细想.今天补题才发现有个 倍增算法,自己竟然不知道. 解法来自 q ...
- 2015长春网络赛1001 求连通快数量的问题dfs
Ponds Time Limit: 1500/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Sub ...
- Hiho coder 1236 2015 北京网络赛 Score
五维偏序..一开始被吓到了,后来知道了一种BITSET分块的方法,感觉非常不错. 呆马: #include <iostream> #include <cstdio> #incl ...
- HDU 5044(2014 ACM-ICPC上海网络赛)
题意:给定一个树形图,节点10^5,有两种操作,一种是把某两点间路径(路径必定唯一)上所有点的权值增加一个固定值. 另一种也是相同操作,不同的是给边加权值.操作次数10^5.求操作过后,每个点和每条边 ...
随机推荐
- Binary search for the first element greater than target
We all know how to search through an array for an element whose value equals the target value, but h ...
- 深入理解c++中char*与wchar_t*与string以及wstring之间的相互转换
本篇文章是对c++中的char*与wchar_t*与string以及wstring之间的相互转换进行了详细的分析介绍,需要的朋友参考下-复制代码 代码如下: #ifndef USE_H_ ...
- UIActinSheet和UIActionSheetDelegate
UIActinSheet和UIActionSheetDelegate 这个是就那个UIActionSheet对象 一般用来选择类型或者改变界面...还有更多应用 定义如下:UIActionSheet ...
- POJ2115——C Looooops(扩展欧几里德+求解模线性方程)
C Looooops DescriptionA Compiler Mystery: We are given a C-language style for loop of type for (vari ...
- Foreman--管理PuppetClient
一. 环境: 1. server: puppetmaster+activemq+foreman1.3 server1.xxx.com(10.8.1.201) 2. client: fedora 19 ...
- 【HDOJ】4251 The Famous ICPC Team Again
划分树模板题目,主席树也可解.划分树. /* 4251 */ #include <iostream> #include <sstream> #include <strin ...
- linux系统中删除文件夹
rm -rf 文件夹的名称 rm-r 文件名称
- IL指令集(转)
名称 说明 Add 将两个值相加并将结果推送到计算堆栈上. Add.Ovf 将两个整数相加,执行溢出检查,并且将结果推送到计算堆栈上. Add.Ovf.Un 将两个无符号整数值相加,执行溢出检查,并且 ...
- 解决windows下vim方向键变成 ABCD 的问题
一.问题描述: windows下面要安装git --> 安装了 msys2 -->安装并更新了 vim(7.4),然后在使用过程中发现vim不能使用 BACKSPACE 键,按方向键会打 ...
- SCOI2009游戏
1025: [SCOI2009]游戏 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 1065 Solved: 673[Submit][Status] ...