CodeForces - 842C Ilya And The Tree

思路:比赛时,写了个树dp,情况考虑少了,赛后才知道gcd的个数是很少的,可以直接暴力,每访问到一个点可以直接去掉这个点或者不去掉这个点,两种情况。开个vector保存这个点gcd的情况,算完之后要去重。

#include<cstdio>
#include<cstring>
#include<cctype>
#include<cstdlib>
#include<iostream>
#include<sstream>
#include<iterator>
#include<algorithm>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#define pr(x) cout << #x << " : " << x << "   "
#define prln(x) cout << #x << " : " << x << endl
#define Size(x) (int)((x).size())
#define fi(x) ((x).first)
#define se(x) ((x).second)
#define Z(x) (*(x))
typedef long long LL;
typedef unsigned long long ULL;
const int INT_INF = 0x3f3f3f3f;
const int INT_M_INF = 0x7f7f7f7f;
const LL LL_INF = 0x3f3f3f3f3f3f3f3f;
const LL LL_M_INF = 0x7f7f7f7f7f7f7f7f;
using namespace std;
inline void debug(char ch){for(int __ii = 0; __ii < 20; ++__ii)putchar(ch);printf("\n");}
const double eps = 1e-8;

#define fin freopen("in.txt", "r", stdin)
#define fout freopen("out.txt", "w", stdout)
const int dr[] = {0, 0, -1, 1, -1, -1, 1, 1};
const int dc[] = {-1, 1, 0, 0, -1, 1, -1, 1};
const int maxn = 21e5 + 10;
vector<int> g[maxn];
int c[maxn];
vector<int> dp[maxn];
int gcd(int x, int y){
    return !y ? x : gcd(y, x % y);
}
void dfs(int u, int f, int gg){
    for(int i = 0; i < g[u].size(); ++i){
        int v = g[u][i];
        if(v == f) continue;
        dp[v].clear();
        dp[v].push_back(gg);
        for(int j = 0; j < dp[u].size(); ++j){
            dp[v].push_back(gcd(dp[u][j], c[v]));
        }
        sort(dp[v].begin(), dp[v].end());
        dp[v].erase(unique(dp[v].begin(), dp[v].end()), dp[v].end());
        int t = gcd(gg, c[v]);
        dfs(v, u, t);
    }
}
int main(){
    int n;
    while(scanf("%d", &n) == 1){
        for(int i = 1; i <= n; ++i) scanf("%d", &c[i]);
        for(int i = 0; i < n - 1; ++i){
            int x, y;
            scanf("%d%d", &x, &y);
            g[x].push_back(y);
            g[y].push_back(x);
        }
        dp[1].push_back(0),dp[1].push_back(c[1]);
        dfs(1, -1, c[1]);
        int flag = 1;
        for(int i = 1; i <= n; ++i){
            if(flag){
                flag = 0;
                printf("%d", dp[i].back());
            }
            else printf(" %d", dp[i].back());
        }
        printf("\n");
    }
}
/*/
6
2 5 4 6 0 0
0 4 1 0 2 3
*/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值