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

题目描述

给定一棵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组测试数据



大意见题面
题解:
首先筛素数,然后把每个合数的约数预处理出来,放在vector里面。
然后从根开始dfs,统计子树中每个val的出现次数,统计进入子树前和从子树回来时增加的出现次数即为F函数的值。
累加答案。
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<ctime>
 5 #include<cstdlib>
 6 #include<algorithm>
 7 #include<cmath>
 8 #include<string>
 9 #include<vector>
10 #include<map>
11 #include<set>
12 using namespace std;
13 int read(){
14     int xx=0,ff=1;char ch=getchar();
15     while(ch>'9'||ch<'0'){if(ch=='-')ff=-1;ch=getchar();}
16     while(ch>='0'&&ch<='9'){xx=xx*10+ch-'0';ch=getchar();}
17     return xx*ff;
18 }
19 const int MOD=1000000007;
20 const int maxn=20010;
21 int N,rt,val[maxn];
22 int lin[maxn],len;
23 struct edge{
24     int y,next;
25 }e[maxn<<1];
26 inline void insert(int xx,int yy){
27     e[++len].next=lin[xx];
28     lin[xx]=len;
29     e[len].y=yy;
30 }
31 inline void ins(int xx,int yy)
32 {insert(yy,xx),insert(xx,yy);}
33 bool vis[maxn];
34 int prime[maxn],cnt=0;
35 vector<int>v[maxn];
36 void pre_prime(){
37     for(int i=2;i<=10000;i++)
38         if(!vis[i]){
39             prime[++cnt]=i;
40             for(int j=i*i;j<=10000;j+=i)
41                 vis[j]=1;
42         }
43     for(int i=2;i<=10000;i++)
44         if(vis[i])
45             for(int j=i;j<=10000;j+=i)
46                 v[j].push_back(i);
47 }
48 int ans,p[maxn];
49 void dfs(int x,int fa){
50     int sum=0;
51     for(int i=0;i<v[val[x]].size();i++)
52         sum-=p[v[val[x]][i]];
53     for(int i=lin[x];i;i=e[i].next)
54         if(e[i].y!=fa)
55             dfs(e[i].y,x);
56     p[val[x]]++;
57     for(int i=0;i<v[val[x]].size();i++)
58         sum+=p[v[val[x]][i]];
59     (ans+=x*sum)%=MOD;
60 }
61 int main(){
62     //freopen("in.txt","r",stdin);
63     pre_prime();
64     for(int T=read();T;T--){
65         memset(lin,0,sizeof(lin));len=0;
66         N=read(),rt=read();
67         for(int i=1;i<N;i++)
68             ins(read(),read());
69         for(int i=1;i<=N;i++)
70             val[i]=read();
71         ans=0;
72         memset(p,0,sizeof(p));
73         dfs(rt,0);
74         printf("%d
",ans);
75     }
76     return 0;
77 }
View Code












原文地址:https://www.cnblogs.com/lzhAFO/p/9038500.html