zoukankan      html  css  js  c++  java
  • Codeforces #430 Div2 C

    #430 Div2 C

    题意

    给出一棵带点权的树,每一个节点的答案为从当前节点到根节点路径上所有节点权值的最大公因子(在求最大共因子的时候可以选择把这条路径上的任意一点的权值置为0)。对于每一个节点单独考虑,输出最大的答案。

    分析

    本以为是一道树形DP,写完就 WA 了。
    补题的时候呢时间复杂度很迷,写完就 T 了。
    一直想着这道题可以抢救一下,还好没看题解,其实只要想想 gcd 的下降速度是很快的,然后就可以乱搞了。

    在搜索的时候记录下前面是否把某个权值当做0来算了,分情况讨论下即可。

    code

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int MAXN = 2e5 + 100;
    struct Edge {
        int to, nxt;
    }e[MAXN << 1];
    int head[MAXN], cnt = 0;
    void add(int u, int v) {
        e[cnt].to = v;
        e[cnt].nxt = head[u];
        head[u] = cnt++;
    }
    int a[MAXN], dp[MAXN];
    
    int gcd(int a, int b) {
        return !b ? a : gcd(b, a % b);
    }
    
    void dfs(int fa, int u, int fac, int is) {
        if(fac == 1) return;
        dp[u] = max(dp[u], fac);
        for(int i = head[u]; ~i; i = e[i].nxt) {
            int v = e[i].to;
            if(v != fa) {
                int gcd_ = gcd(fac, a[v]);
                if(is && gcd_ > 1) {
                    dfs(u, v, gcd_, 1);
                } else if(!is) {
                    if(gcd_ < fac) {
                        if(gcd_ > 1) dfs(u, v, gcd_, 0); // 看似很暴力,但是注意到 gcd 的下降速度是很快的,且保证了 gcd_ < fac 。
                        dfs(u, v, fac, 1);
                    }
                    else dfs(u, v, fac, 0);
                }
            }
        }
    }
    //适用于正整数
    template <class T>
    inline void scan_d(T &ret) {
        char c; ret=0;
        while((c=getchar())<'0'||c>'9');
        while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar();
    }
    int main() {
        memset(head, -1, sizeof head);
        int n;
        scan_d(n);
        for(int i = 1; i <= n; i++) {
            scan_d(a[i]);
            dp[i] = 1;
        }
        for(int i = 1; i < n; i++) {
            int u, v;
            scan_d(u); scan_d(v);
            add(u, v);
            add(v, u);
        }
        dfs(0, 1, 0, 1);
        dfs(0, 1, a[1], 0);
        for(int i = 1; i <= n; i++) {
            printf("%d%c", dp[i], " 
    "[i == n]);
        }
        return 0;
    }
    
  • 相关阅读:
    JDBC连接MySQL并且查询操作。
    struts
    KMP 剪花布条hdoj2087
    线段树---敌兵布阵hdoj 1166
    设计模式----观察者模式
    线段树--hdoj1754
    ZOJ 2283 Challenge of Wisdom
    SGU 134 Centroid
    UVA 1637 Double Patience
    HDU 4389 X mod f(x)
  • 原文地址:https://www.cnblogs.com/ftae/p/7454843.html
Copyright © 2011-2022 走看看