B 合约数

链接:https://www.nowcoder.com/acm/contest/91/B
来源:牛客网

题目描述

在埃森哲,员工培训是最看重的内容,最近一年,我们投入了 9.41 亿美元用于员工培训和职业发展。截至 2018 财年末,我们会在全球范围内设立 100 所互联课堂,将互动科技与创新内容有机结合起来。按岗培训,按需定制,随时随地,本土化,区域化,虚拟化的培训会让你快速取得成长。小埃希望能通过培训学习更多ACM 相关的知识,他在培训中碰到了这样一个问题,

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

输入描述:

输入测试组数T,每组数据,输入n+1行整数,第一行为n和p,1<=n<=20000, 1<=p<=n, 接下来n-1行,每行两个整数u和v,表示u和v之间有一条边。第n+1行输入n个整数val1, val2,…, valn,其中1<=vali<=10000,1<=i<=n.

输出描述:

对于每组数据,输出一行,包含1个整数, 表示对1000000007取模后的结果

示例1

输入

2
5 4
5 3
2 5
4 2
1 3
10 4 3 10 5
3 3
1 3
2 1
1 10 1

输出

11
2

备注:

n>=10000的有20组测试数据

dfs问题,先预处理下10000之内的每个合约数,然后从根节点p开始遍历,每次删除前面出现的合约数,等回溯后就加上当前的合约数,这样就可以得到当前的合约数了。

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <cstring>
 4 #include <vector>
 5 using namespace std;
 6 const int mod = 1000000007;
 7 const int M = 20010;
 8 vector<int> vs[M], H[M];
 9 bool vis[M];
10 int val[M], F[M], ans, cnt[M];
11 void init() {
12     vis[0] = vis[1] = true;
13     for(int i = 2; i <= 100; i ++) {
14         if(!vis[i]) {
15             for(int j = i*i; j <= 10000; j += i) vis[j] = true;
16         }
17     }
18     for(int i = 4; i <= 10000; ++ i) {
19         if(vis[i]) {
20             for(int j = 4; j <= i; ++ j) {
21                 if(vis[j] && i%j == 0) H[i].push_back(j);
22             }
23         }
24     }
25 }
26 void dfs(int u) {
27     for(int i = 0; i < H[val[u]].size(); i ++) {
28         F[u] -= cnt[H[val[u]][i]];
29     }
30     cnt[val[u]]++;
31     for(int i = 0; i < vs[u].size(); i ++) {
32         if(!vis[vs[u][i]]) {
33             vis[vs[u][i]] = 1;
34             dfs(vs[u][i]);
35         }
36     }
37     for(int i = 0; i < H[val[u]].size(); i ++) {
38         F[u] += cnt[H[val[u]][i]];
39     }
40     ans += 1LL*F[u]*u;
41     ans %= mod;
42 }
43 int main() {
44     init();
45     //printf("%d
",H[10].size());
46     int t, n, p;
47     cin >> t;
48     while(t--) {
49         memset(vis,0,sizeof(vis));
50         memset(F,0,sizeof(F));
51         memset(cnt,0,sizeof(cnt));
52         for(int i = 0; i <= M; i ++) vs[i].clear();
53         ans = 0;
54         cin >> n >> p;
55         for(int i = 0; i < n-1; i ++) {
56             int u, v;
57             cin >> u >> v;
58             vs[u].push_back(v);
59             vs[v].push_back(u);
60         }
61         for(int i = 1; i <= n; i ++) cin >> val[i];
62         vis[p] = 1;
63         dfs(p);
64         cout << ans << endl;
65     }
66     return 0;
67 }
原文地址:https://www.cnblogs.com/xingkongyihao/p/8870132.html