Since both Stefan and Damon fell in love with Elena, and it was really difficult for her to choose. Bonnie, her best friend, suggested her to throw a question to them, and she would choose the one who can solve it.
Suppose there is a tree with n vertices and n - 1 edges, and there is a value at each vertex. The root is vertex 1. Then for each vertex, could you tell me how many vertices of its subtree can be said to be co-prime with itself?
NOTES: Two vertices are said to be co-prime if their values' GCD (greatest common divisor) equals 1.
Input
There are multiply tests (no more than 8).
For each test, the first line has a number nn (1≤n≤105)(1≤n≤105), after that has n−1n−1lines, each line has two numbers a and b (1≤a,b≤n)(1≤a,b≤n), representing that vertex a is connect with vertex b. Then the next line has n numbers, the ithith number indicates the value of the ithith vertex. Values of vertices are not less than 1 and not more than 105105.
Output
For each test, at first, please output "Case #k: ", k is the number of test. Then, please output one line with n numbers (separated by spaces), representing the answer of each vertex.
Sample Input
5
1 2
1 3
2 4
2 5
6 2 3 4 5
Sample Output
Case #1: 1 1 0 0 0
题解:
预处理,保存每个数的因子
100000 约数最多6个 2 * 3 * 5 * 7 * 11 * 13 = 30030
容斥原理求不互质的个数,sum[i]保存 累计以i为约数的个数,找到一个点时,先保存之前出现的次数,然后在dfs,互质的个数即为 孩子个数 - 不互质个数
特!!! 该点为1的话 1与1的gcd也为1
#include<bits/stdc++.h>
using namespace std;
#define PI acos(-1)
const int N=1e5+10;
vector<int> prime[N];
vector<int> v[N];
int sum[N],ans[N],a[N],son[N];
bool ok[N];
int n;
void init()
{
for(int i=2;i<=N-10;i++)
{
if(ok[i])continue;
for(int j=i;j<=N-10;j+=i)
{
prime[j].push_back(i);
ok[j]=1;
}
}
}
void dfs(int u,int f)
{
int p[65];
int l=prime[a[u]].size();
int len=1<<l;
for(int i=1;i<len;i++)
{
int tmp=1;
for(int j=0;j<l;j++)
if((1<<j)&i)
tmp*=prime[a[u]][j];
p[i]=sum[tmp];
}
l=v[u].size();
for(int i=0;i<l;i++)
{
if(v[u][i]!=f)
{
dfs(v[u][i],u);
son[u]+=son[v[u][i]];
}
}
l=prime[a[u]].size();
// cout<<l<<endl;
for(int i=1;i<len;i++)
{
int tmp=1;
int cnt=0;
for(int j=0;j<l;j++)
{
if((1<<j)&i)
{
tmp*=prime[a[u]][j];
cnt++;
}
}
// cout<<cnt<<" "<<tmp<<endl;
if(cnt&1) ans[u]+=sum[tmp]-p[i];//容斥 奇数+ 偶数-
else ans[u]-=sum[tmp]-p[i];
sum[tmp]++;
}
ans[u]=son[u]-ans[u];
son[u]++;
if(a[u]==1) ans[u]+=1;
}
int main()
{
init();
int nn=1;
while(~scanf("%d",&n))
{
for(int i=0;i<=n;i++)
sum[i]=ans[i]=son[i]=0,v[i].clear();
int x,y;
for(int i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
v[x].push_back(y);
v[y].push_back(x);
}
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
dfs(1,0);
printf("Case #%d: ",nn++);
for(int i=1;i<=n;i++)
printf("%d%c",ans[i]," \n"[i==n]);
}
return 0;
}