链接:https://ac.nowcoder.com/acm/contest/9115/B

题意:给定一棵n个节点的树,并且根节点的编号为p,第i个节点有属性值vali, 定义F(i): 在以i为根的子树中,属性值是vali的合约数的节点个数。y 是 x 的合约数是指 y 是合数且 y 是 x 的约数。小埃想知道对1000000007取模后的结果。

思路1:反向思考,对于一个编号u,他自己对其子树中是他合约数的节点的贡献为u。用素数筛的思想,预处理每个数的约数以及是否为合数。假设dfs到一个节点u,先将val[u]的约数都加上其贡献u,然后判断val[u]是否为合数,如果是就将当前val[u]得到的贡献都加在答案上。之后dfs子树,搜完之后要将val[u]的对其约数贡献u去掉,因为u只对其子树的合约数有贡献,避免u对他的兄弟也产生贡献。注意初始化!

代码1:

 #include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e4+10;
const int mod = 1e9+7;
bool book[N],vis[N<<1];
vector<int> fac[N],g[N<<1];
int t,n,root,val[N<<1],pri[N<<1],cnt=0;
ll ans,f[N];
void init(){book[1]=0;for(int i=2;i<N;i++){if(!book[i]) pri[++cnt]=i;for(int j=1;j<=cnt&&i*pri[j]<N;j++){book[i*pri[j]]=1;if(i%pri[j]==0) break;}}for(int i=1;i<N;i++){for(int j=i;j<N;j+=i){fac[j].push_back(i);    }}
}
void dfs(int u,int fa){for(int i=0;i<fac[val[u]].size();i++){int v = fac[val[u]][i];f[v]=(f[v]+u)%mod;}if(book[val[u]]) ans=(ans+f[val[u]])%mod;for(int i=0;i<g[u].size();i++){int v=g[u][i];if(v==fa) continue;dfs(v,u);}  for(int i=0;i<fac[val[u]].size();i++){int v = fac[val[u]][i];f[v]=(f[v]-u)%mod;}
}
int main(void){scanf("%d",&t);init();while(t--){scanf("%d%d",&n,&root);ans=0;for(int i=1;i<=n;i++) g[i].clear();    for(int i=1;i<N;i++) f[i]=0; for(int i=1;i<n;i++){int u,v;scanf("%d%d",&u,&v);g[u].push_back(v);g[v].push_back(u);}for(int i=1;i<=n;i++)scanf("%d",&val[i]);    dfs(root,-1);   printf("%lld\n",ans);}return 0;
} 

思路2:dsu on tree,还是要预处理是否为合数以及每个数的因子。维护每个数的个数,统计答案时,看一下每个数的合约数有多少就行了。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e4+10;
const ll mod = 1e9+7;
bool book[N];
int pri[N],cnt;
vector<int> fac[N];
void prime(){book[1]=0;for(int i=2;i<N;i++){if(!book[i]) pri[++cnt]=i;for(int j=1;j<=cnt&&i*pri[j]<N;j++){book[i*pri[j]]=1;if(i%pri[j]==0) break;}}for(int i=1;i<N;i++)for(int j=i;j<N;j+=i)fac[j].push_back(i);
}
int n,p,val[N<<1];
vector<int> g[N<<1];
ll ans;
int num[N];
bool big[N<<1];
void init(){ans=0;memset(num,0,sizeof num);for(int i=1;i<=n;i++){g[i].clear();big[i]=0;}
}
int sz[N<<1];void getsz(int u,int fa){sz[u]=1;int siz=g[u].size();for(int i=0;i<siz;i++){int v=g[u][i];if(v==fa) continue;getsz(v,u);sz[u]+=sz[v];}
}void dfs1(int u,int fa,int x){num[val[u]]+=x;int siz=g[u].size();for(int i=0;i<siz;i++){int v=g[u][i];if(v==fa||big[v]) continue;dfs1(v,u,x);}
}
void dfs(int u,int fa,bool keep){int mx=-1,bigc=-1;int siz=g[u].size();for(int i=0;i<siz;i++){int v=g[u][i];if(v==fa) continue;if(sz[v]>mx) mx=sz[v],bigc=v;}for(int i=0;i<siz;i++){int v=g[u][i];if(v==fa||v==bigc) continue;dfs(v,u,0);}if(bigc!=-1){dfs(bigc,u,1);big[bigc]=1;}dfs1(u,fa,1);siz=fac[val[u]].size();for(int i=0;i<siz;i++)if(book[fac[val[u]][i]]){ans=(ans+u*num[fac[val[u]][i]])%mod;}if(bigc!=-1) big[bigc]=0;if(keep==0)dfs1(u,fa,-1);
}
int main(void){int t;prime();scanf("%d",&t);while(t--){scanf("%d%d",&n,&p);init();for(int i=1;i<n;i++){int u,v;scanf("%d%d",&u,&v);g[u].push_back(v);g[v].push_back(u);}for(int i=1;i<=n;i++) scanf("%d",&val[i]);getsz(p,0);dfs(p,0,0); printf("%lld\n",ans);}return 0;
} 

埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛 B 合约数 (dfs+预处理)(dsu on tree)相关推荐

  1. 埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛 L-K序列

    埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛 L-K序列 链接:https://www.nowcoder.com/acm/contest/91/L 来源:牛客网 题目描述 给一个数组 ...

  2. 埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛 A-Wasserstein Distance

    埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛 A-Wasserstein Distance 链接:https://www.nowcoder.com/acm/contest/91/A ...

  3. 埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛 E-小Y吃苹果

    埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛 E-小Y吃苹果 链接:https://www.nowcoder.com/acm/contest/91/E 来源:牛客网 题目描述 小Y买 ...

  4. 好久没撸c,第一场回状态的题(埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛

    题目链接: 埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛 A:Wasserstein Distance ## 题意:有2大堆柱状图的土(总体积相同,问从第一堆土移动到第二堆消耗最少的 ...

  5. 埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛 I 二数(模拟)

    题目描述  我们把十进制下每一位都是偶数的数字叫做"二数". 小埃表示自己很聪明,最近他不仅能够从小数到大:2,3,4,5....,也学会了从大数到小:100,99,98...,他 ...

  6. 埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛B合约数

    链接:https://www.nowcoder.com/acm/contest/91/B 来源:牛客网 题目描述 在埃森哲,员工培训是最看重的内容,最近一年,我们投入了 9.41 亿美元用于员工培训和 ...

  7. 【牛客网】埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛 题解

    题目连接 A.Wasserstein Distance (水题) 题意:给你2行土a,b,每行都有n堆,每堆对应有a[i],b[i]克,我们可以对a中的土进行移动,移动任意堆的k克泥土到a中其他堆消耗 ...

  8. 二数 (埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛)...

    题目描述 我们把十进制下每一位都是偶数的数字叫做"二数". 小埃表示自己很聪明,最近他不仅能够从小数到大:2,3,4,5....,也学会了从大数到小:100,99,98...,他想 ...

  9. 埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛 C序列变换...

    链接:https://www.nowcoder.com/acm/contest/91/C 来源:牛客网 没有账号的同学这样注册,支持博主 题目描述 给定两个长度为n的序列,ai, bi(1<=i ...

最新文章

  1. C#编码简单性之语义篇(如何编写简短的C#代码,随时更新)
  2. android自动填充包名,debug/release 修改包名,取不同包名下的agconnect-services.json 文件...
  3. 求1/2+1/4+...+1/n
  4. @RequestMapping,@ResponseBody,@RequestBody用法
  5. 【收藏】CentOS 7 安装NFS
  6. 如何使用Fiddler调试线上JS代码(转自:http://www.cnblogs.com/RockLi/p/3511132.html)
  7. 如何理解和分析linux系统的CPU平均负载情况(load average)
  8. User Experience Kit
  9. html5情人节贺卡,Web工程师的情人节卡片
  10. 数据库连接字符串 mysql_数据库连接字符串(MySQL,SQL Server,Oracle)
  11. 条件查询_多条件组合查询---测试用例设计
  12. 脉脉第一干货贴,互联网职场那点事,关于面试、绩效、晋升、职业规划。
  13. topcoder srm 525 div1
  14. 30.构建单机多容器环境-故障31.构建单机多容器环境
  15. Atitit redis使用场合总结 使用场景 目录 1.1. 3. Session 存储 1 1、 配置数据查询 1 2. 排行榜应用,取TOP N操作 1 1.2.     1、查找最
  16. 修复inspinia中popover的点击问题
  17. 真实数据揭秘游戏主播能否月入100万
  18. jquery ajax添加ul li,jQuery.ajax动态添加标签无法被获取到
  19. 基于HTML的环境网站设计 HTML+CSS环保网站项目实现 带设计说明psd
  20. 以下是两段c语言代码函数arith,计算机组成习题答案(清华大学).docx

热门文章

  1. python学习爬虫之删除无用字符以及空白替换等()
  2. 牛客网暑期ACM多校训练营(第十场)D Rikka with Prefix Sum
  3. 【JavaScript】性能优化
  4. 用Windows Live Writer写CSDN博客和网易博客
  5. jenkins接入企业微信提醒
  6. 我说百度很垃圾的10条理由
  7. unsigned int a : 1;含义
  8. 计算机网络系统有哪些核心技术,超级计算机的核心技术是什么
  9. 《当程序员的那些狗日日子》(四十四)是办公室还是牢房
  10. 明日之后双人十庄房子蓝图_明日之后和同居的那些事