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 n
(1≤n≤105)
, after that has n−1 lines, each line has two numbers a and b (1≤a,b≤n), representing that vertex a is connect with vertex b. Then the next line has n numbers, the ith number indicates the value of the ith vertex. Values of vertices are not less than 1 and not more than 105
.
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
递归里面可以开数组,但是不能开太大,要不然会爆栈的
一棵树的每个节点的 因子是有限的, 我们不可能遍历一棵树好多次,所以我们考虑
容斥定理+前缀和(一般很多的话,差值很常见)
对于一个节点,我们知道他的子树一共有n个点,那么和 子树的根不互质的,就是有他的各个因子的数量。
#include
using namespace std;
typedef long long LL;
#pragma comment(linker, “/STACK:1024000000,1024000000”)
#define rep(i,a,b) for(int i=a;i=a;--i)
const int N=1e5+10;
vector vec[N];
bool vis[N];
void init(){
for(int i=2;i
还有一种就是直接预处理在 递归体里面做的拆分(也就是莫比乌斯)
#include
#include
#include
#include
#include
using namespace std;
const int maxn = 100000;
int mu[maxn + 10], pcnt, prime[maxn];
bool vis[maxn + 10];
vector factors[maxn + 10];
vector G[maxn + 10];
void init() {
pcnt = 0;
mu[1] = 1;
for(int i = 2; i <= maxn; i++) {
if(!vis[i]) {
mu[i] = -1;
prime[pcnt++] = i;
}
for(int j = 0; j < pcnt && i * prime[j] <= maxn; j++) {
vis[i * prime[j]] = true;
if(i % prime[j] != 0) mu[i * prime[j]] = -mu[i];
else {
mu[i * prime[j]] = 0;
break;
}
}
}
//如果mu[i]不为0,说明他是 单个素因子的乘积
for(int i = 2; i <= maxn; i++) if(mu[i]) for(int j = i; j <= maxn; j += i) factors[j].push_back(i);
}
int val[maxn + 10];
int n;
int cnt[maxn], sz[maxn], ans[maxn];
void dfs(int u, int fa) {
sz[u] = 1;
vector pre;
for(int d : factors[val[u]]) {
pre.push_back(cnt[d]);//保留下他在遍历子树之前的因子的sum值
cnt[d]++;
}
for(int v : G[u]) {
if(v == fa) continue;
dfs(v, u);
sz[u] += sz[v];
}
ans[u] = sz[u];
for(int i = 0; i < factors[val[u]].size(); i++) {
int d = factors[val[u]][i];
int c = cnt[d] - pre[i];
if(c) ans[u] += mu[d] * c;
}
}
int main()
{
init();
int kase = 1;
while(scanf("%d", &n) == 1 && n) {
for(int i = 1; i <= n; i++) G[i].clear();
for(int u, v, i = 1; i < n; i++) {
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);
memset(cnt, 0, sizeof(cnt));
dfs(1, 0);
printf("Case #%d:", kase++);
for(int i = 1; i <= n; i++) printf(" %d", ans[i]);
printf("\n");
}
return 0;
}