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

解题思路:题利用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个素因子的个数}。这恰好就是容斥原理。至此,问题得以解决。

  1 #include<cstdio>
  2 #include<cmath>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<iostream>
  6 #include<memory.h>
  7 #include<cstdlib>
  8 #include<vector>
  9 #define clc(a,b) memset(a,b,sizeof(a))
 10 #define LL long long int
 11 using namespace std;
 12 const int N=100010;
 13 const double eps=1e-8;
 14 const int inf=0x3f3f3f3f;
 15
 16 int n;
 17 int val[N];
 18 int ans[N];
 19 int e;
 20 int num[N];
 21 int head[N];
 22 vector<int>g[N];
 23 struct Edge
 24 {
 25     int to,next;
 26 }edge[N*2];
 27
 28 void add(int u,int v)
 29 {
 30    edge[e].to=v;
 31    edge[e].next=head[u];
 32    head[u]=e++;
 33 }
 34
 35 void init()
 36 {
 37     for(int i=2;i<N;i++)
 38     {
 39         if(!g[i].empty())
 40             continue;
 41         for(int j=i;j<N;j+=i)
 42             g[j].push_back(i);
 43     }
 44 }
 45
 46 int calc(int x,int y)//*y=0表示进入这颗树的时候,含有互质的数目为0;y=1表示dfs回溯的时候离开这棵树相应互质节点数目加一*//
 47 {
 48     int len=g[x].size();
 49     int res=0;
 50     for(int i=1;i<(1<<len);i++)
 51     {
 52         int t=1;
 53         int cnt=0;
 54         for(int j=0;j<len;j++)
 55         {
 56             if(i&(1<<j))
 57             {
 58                 cnt++;
 59                 t=t*g[x][j];
 60             }
 61         }
 62         if(cnt%2)
 63             res+=num[t];
 64         else
 65             res-=num[t];
 66         num[t]+=y;
 67     }
 68     return res;
 69 }
 70 int dfs(int u,int pre)
 71 {
 72     int cnt=0;
 73     int L=calc(val[u],0);
 74     for(int i=head[u];~i;i=edge[i].next)
 75     {
 76         int v=edge[i].to;
 77         if(v==pre)
 78             continue;
 79         cnt+=dfs(v,u);
 80     }
 81     int R=calc(val[u],1);
 82     ans[u]=cnt-(R-L);
 83     if(val[u]==1)
 84     ans[u]++;
 85     return cnt+1;
 86 }
 87 int main()
 88 {
 89     int u,v;
 90     int cas=1;
 91     while(~scanf("%d",&n))
 92     {
 93         e=0;
 94         init();
 95         clc(num,0);
 96         clc(head,-1);
 97         for(int i=0;i<n-1;i++)
 98         {
 99             scanf("%d%d",&u,&v);
100             add(u,v);
101             add(v,u);
102         }
103         for(int i=1;i<=n;i++)
104         {
105             scanf("%d",&val[i]);
106         }
107         dfs(1,0);
108         printf("Case #%d:",cas++);
109         for(int i=1;i<=n;i++)
110         {
111            printf(" %d",ans[i]);
112         }
113         printf("\n");
114     }
115     return 0;
116 }

View Code

转载于:https://www.cnblogs.com/ITUPC/p/4867364.html

2015上海网络赛 A Puzzled Elena相关推荐

  1. 2019 ACM - ICPC 上海网络赛 E. Counting Sequences II (指数型生成函数)

    繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我写的超高质量题解和代码,题目难度不一定按照题号排序,我会在每道题后面加上题目难度指数(1∼51 \sim 51∼5),以模板题难度 11 ...

  2. 树形DP+并查集+左偏树, HDU-5575,Discover Water Tank,2015上海现场赛D题

    只是ACM/IICPC 2015 上海区域赛的一道题.原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=5575 题目描述 N-1个木板把一个水箱划分成了N ...

  3. 2015长春网络赛 —— B. Ponds (拓扑排序删点+DFS)

    题目描述 Description Betty owns a lot of ponds, some of them are connected with other ponds by pipes, an ...

  4. hdu5489(2015合肥网络赛F题)

    转载自:http://blog.csdn.net/lwt36/article/details/48774103 题意: 给出一个数列,在其中删除连续的L个数字,使得剩余的数字LIS最大,输出此LIS. ...

  5. hdu5491(2015合肥网络赛H题)

    题意: 给出三个数字D.s1和s2,用L来表示D的二进制表示中1的个数,L在区间[s1,s2]中,我们要找到离D最近的并且大于D的一个数字,且这个数字的L也落在区间[s1,s2]中. 思路: 一直超时 ...

  6. hdu5492(2015合肥网络赛I题)

    题意: n*m的格子,每个格子有权值,我们要从左上角走到右下角,只能向下走或者向右走,求走到终点走过的格子的方差的最小值. 思路: 被这题坑了,我还是太蠢. 我们可以暴力(∑Ai)^2,取最优就好了. ...

  7. hihoCoder1233(2015北京网络赛H题)

    转载自:http://blog.csdn.net/queuelovestack/article/details/48625899 题意: 有n个卡槽,放有体积不同的n个空盒子,每次你可以移动一个空盒子 ...

  8. hihoCoder1228(2015北京网络赛B题)

    题意: 给出一个文本编辑器的容量,给出老板输入的字符串,小写字母代表文本,大写字母代表命令: L:光标左移: R:光标右移: S:在insert模式和另一个输入模式中切换: D:删除光标后面的一个字符 ...

  9. hdu5461(2015沈阳网络赛L题)

    题意: 给出一个数列,我们要在这里找出两个数,使得题意中那个表达式最大. 思路: 排两个序就好了啊,看代码一下就懂了. 代码: #include <cstdio> #include < ...

最新文章

  1. python零基础怎么学-编程零基础应当如何开始学习 Python?
  2. PPT 图片python处理
  3. AOP开发——在不修改源代码的前提下,对类里面的方法进行增强 : 前置 后置 环绕 异常||如何得到目标方法的参数和返回值
  4. Orace 11g 监听 配置修改 说明
  5. .net 把一个对象赋值给一个参数_Java:new一个对象的过程中发生了什么?
  6. 转: Div与table的区别
  7. Spring Boot 多数据源(读写分离)入门
  8. xcode 工程没有模拟器_Xcode只允许我运行iOS设备(没有模拟器)
  9. 2021年中国以太网转换器市场趋势报告、技术动态创新及2027年市场预测
  10. EntityModelStudio系列教程
  11. 通过v$sqlarea,v$sql查询最占用资源的查询
  12. SVN回滚代码时,提示冲突怎么办
  13. Java实现冒泡排序算法
  14. JAVA高端编程研发培训班 JAVA开发视频教程
  15. 参考文献引用格式实例
  16. Java 工程师修炼之道
  17. 电信中兴f452光猫路由改桥接最简单的方式,亲自体验成功。
  18. 哪些行业申请网站备案时需要提供前置或专项审批文件?
  19. 获取汉字的拼音码(工具类)
  20. 贪心算法之田忌赛马(超详细)

热门文章

  1. python获取汉字拼音查询翻译器_python获取汉字的拼音
  2. 无线通信设计秘密三:效率 节能 组网
  3. 再融40亿,哈罗单车为何能在“寒冬”中逆势崛起?
  4. 某验4代文字点选逆向分析(一)
  5. 恋爱话术源码微信公众号版
  6. Java学习-35天
  7. MCU震荡电路晶振旁边两个22pf电容的作用
  8. word中表中横线断开的排法
  9. 金融行业密钥体系相关知识及原理介绍
  10. 上海大学计算机工程与科学学院院长,我校校友谢少荣应邀回母校交流并受聘顾问教授...