hdu 5468(dfs序+容斥原理)

Puzzled Elena

Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 1247    Accepted Submission(s): 370

Problem Description

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

Source

2015 ACM/ICPC Asia Regional Shanghai Online

题意:给定 n 个结点 n-1条边的一棵树 ,每个结点都有一个 value,问每个节点的子节点的value与其value互素的个数有多少?

题解:我们可以先预处理出 1 ~ 10^5 内所有整数的因子,然后进行 DFS,当进入结点 u 时,记录当前与 u 不互素的数的个数为 a ,出节点 u 时,记录这时与 u不互素的个数为b,那么 u 的子树中 与 value[u] 不互素的个数就为 b-a ,当前结点 u 的子节点结点个数为 s,那么与 其互素的数个数为 s - (b-a).这里用一个 cnt[i]数组记录当前含有因数 i 的结点的个数,每次退出结点 u 的时候要将含有其因子的数量累加.还有就是当 val[u] == 1时,他与本身互素,答案 +1 .

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <bits/stdc++.h>
using namespace std;
typedef long long  LL;
const int N = 100005;
vector <int> factor[N];
vector <int> edge[N];
void init(){
    for(int i=2;i<N;i++){
        factor[i].clear();
        int n = i;
        for(int j=2;j*j<=n;j++){
            if(n%j==0){
                factor[i].push_back(j);
                while(n%j==0) n/=j;
            }
        }
        if(n>1) factor[i].push_back(n);
    }
}
int cnt[N]; ///cnt[i]表示遍历到当前结点时候,含有因数i的结点个数。
int val[N];
int ans[N];
int solve(int n,int val){
    int len = factor[n].size(),ans=0;
    for(int i=1;i<(1<<len);i++){
        int odd = 0;
        int mul = 1;
        for(int j=0;j<len;j++){
            if((i>>j)&1){
                odd++;
                mul*=factor[n][j];
            }
        }
        if(odd&1){
            ans+=cnt[mul];
        }
        else ans-=cnt[mul];
        cnt[mul]+=val; /// val = 1 代表退出当前结点时把因子加上
    }
    return ans;
}
int dfs(int u,int pre){
    int L = solve(val[u],0);  ///第一次遍历到 u,拥有与 u 相同的因子个数
    int s = 0; ///s 代表当前结点下的子节点数目
    for(int i=0;i<edge[u].size();i++){
        int v = edge[u][i];
        if(v==pre) continue;
        s+=dfs(v,u);
    }
    int R = solve(val[u],1);
    ans[u] = s - (R-L);
    if(val[u]==1) ans[u]++;
    return s+1;
}
int main()
{
    init();
    int n,t = 1;
    while(scanf("%d",&n)!=EOF){
        memset(cnt,0,sizeof(cnt));
        for(int i=1;i<=n;i++) edge[i].clear();
        for(int i=1;i<n;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            edge[u].push_back(v);
            edge[v].push_back(u);
        }
        for(int i=1;i<=n;i++){
            scanf("%d",&val[i]);
        }
        dfs(1,-1);
        bool flag = true;
        printf("Case #%d: ",t++);
        for(int i=1;i<=n;i++){
            if(!flag) printf(" ");
            flag = false;
            printf("%d",ans[i]);
        }
        printf("\n");
    }
    return 0;
}
时间: 2024-10-11 00:44:38

hdu 5468(dfs序+容斥原理)的相关文章

HDU 3966 dfs序+LCA+树状数组

题目意思很明白: 给你一棵有n个节点的树,对树有下列操作: I c1 c2 k 意思是把从c1节点到c2节点路径上的点权值加上k D c1 c2 k 意思是把从c1节点到c2节点路径上的点权值减去k Q a 查询节点a的权值 数据大小 节点个数 n[1,50000], 操作次数 op[0,30000]; 不会树链剖分 故只有想其他的方法. 这道题有点类似今年上海网络赛的1003 ,不过那题我没做: 算法思路: 以节点1 为根,求出节点i 的 dfs序列 tim[i][2]; 其中tim[i][0

HDU Hilarity (dfs序+线段树)

Problem Description After June 1st, elementary students of Ted Land are still celebrating "The Sacred Day of Elementary Students". They go to the streets and do some elementary students stuff. So we call them "elementary students". The

HDU5468(dfs序+容斥原理)

Puzzled Elena Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 1162    Accepted Submission(s): 339 Problem Description Since both Stefan and Damon fell in love with Elena, and it was really dif

HDU 6203 ping ping ping(dfs序+LCA+树状数组)

http://acm.hdu.edu.cn/showproblem.php?pid=6203 题意: n+1 个点 n 条边的树(点标号 0 ~ n),有若干个点无法通行,导致 p 组 U V 无法连通.问无法通行的点最少有多少个. 思路: 贪心思维,破坏两个点的LCA是最佳的.那么怎么判断现在在(u,v)之间的路径上有没有被破坏的点呢,如果没有的话那么此时就要破坏这个lca点.一开始我们要把询问按照u和v的lca深度从大到小排序,如果某个点需要被破坏,那么它的所有子节点都可以不再需要破坏别的点

HDU 5156 - Harry and Christmas tree (dfs序+离线树状数组)

http://acm.hdu.edu.cn/showproblem.php?pid=5156 BC#25的C题. 题意是:给出一颗大小为n的树,以1为根,然后给出m次染色,每次将节点u加上一种颜色(一个节点可以有多个颜色). 最后查询树上每个节点对应子树上包含的不同颜色数量. 当时这场比赛没有做,回来看一下题目,没看标解就试着敲了一遍,于是解题思路从一开始就走上了不归路. 标解是O(n+m)的方法,主要思路是将问题转为:一次染色表示将u到根节点的路径都染上这种颜色. 但这样做需要去重,因为如果u

hdu 6191 Query on A Tree(dfs序+可持久化字典树)

题目链接:hdu 6191 Query on A Tree 题意: 给你一棵树,每个节点有一个值,现在有q个询问,每个询问 询问一个u x,问以u为根的子树中,找一个节点,使得这个节点的值与x异或的值最大,输出那个最大的值. 题解: dfs序和一棵可持久化字典树就搞定了. 1 #include<bits/stdc++.h> 2 #define mst(a,b) memset(a,b,sizeof(a)) 3 #define F(i,a,b) for(int i=a;i<=b;++i) 4

HDU 5293 Tree chain problem 树形dp+dfs序+树状数组+LCA

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5293 题意: 给你一些链,每条链都有自己的价值,求不相交不重合的链能够组成的最大价值. 题解: 树形dp, 对于每条链u,v,w,我们只在lca(u,v)的顶点上处理它 让dp[i]表示以i为根的指数的最大值,sum[i]表示dp[vi]的和(vi为i的儿子们) 则i点有两种决策,一种是不选以i为lca的链,则dp[i]=sum[i]. 另一种是选一条以i为lca的链,那么有转移方程:dp[i]=

[HDU 5296] Annoying problem (DFS序性质+LCA)

HDU - 5296 一棵树上有若干个点,每条边有一个边权 给一个初始为空的集合,每次向集合内添加一个点或者删除一个点 问每次操作结束后,将集合内所有点连起来的边权和为多少 假设集合内已经有一些点,那么再加一个点所增加的边权 将会是这个点到某一条链的距离 但是这条链不能随便挑选,否则可能会经过已经选择的边 挑选策略就是,找到集合内dfs序比当前点大和小的两个点组成的链 换句话来说,就是集合内dfs序最靠近当前点的两个点 设当前点 x,这样选链,选出的链是 (u,v),并且设dfsn[u]<dfs

HDU 3887 Counting Offspring(DFS序求子树权值和)

Problem Description You are given a tree, it's root is p, and the node is numbered from 1 to n. Now define f(i) as the number of nodes whose number is less than i in all the succeeding nodes of node i. Now we need to calculate f(i) for any possible i