美文网首页
CF1101 D GCD Counting

CF1101 D GCD Counting

作者: zjsdut | 来源:发表于2019-01-12 22:29 被阅读0次

犯了一个愚蠢的错误。

vb vis(N);
vi a(N);
vv<int> p(N);
vv<int> g(N);


vector<map<int,int>> f(N);
int ans = 0;

void dfs(int u) {
    vis[u] = true;
    int t = a[u];

    map<int,int> b1, b2;

    FOR(x, p[t]) {
        f[u][x] = 1;
    }

    FOR(v, g[u]) {
        if(!vis[v]) {
            dfs(v);
            FOR(x, p[t]) {
                auto iter = f[v].find(x);
                if(iter != f[v].end()) {
                    int tmp = iter->second;
                    if (b1[x] < tmp) {
                        b2[x] = b1[x];
                        b1[x] = tmp;
                    }
                    else if(b2[x] < tmp) {
                        b2[x] = tmp;
                    }
                }
            }
        }
    }

    FOR(x, p[t]) {
         f[u][x] += b1[x] + b2[x];
         ans = max(ans, f[u][x]);
    }
}

int main() {
    FAST_READ
#ifdef LOCAL
    ifstream in("main.in");
    cin.rdbuf(in.rdbuf());
#endif

    const int maxn = 2e5+5;

    vb isp(maxn, true);

    rng(i, 2, maxn) {
        if(isp[i]) {
            p[i].pb(i);
            stp(j, 2*i, maxn, i) {
                isp[j] = false;
                p[j].pb(i);
            }
        }
    }

    int n; cin >> n;

  rng(i, 1, n+1) {
        cin >> a[i];
    }

    rep(n-1) {
        int u, v;
        scan(u, v);
        if(__gcd(a[u], a[v]) >1) {
            g[u].pb(v);
            g[v].pb(u);
        }
    }

    rng(i, 1, n + 1) {
      if(!vis[i]) dfs(i);
  }

  println(ans)

#ifdef LOCAL
    cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
    return 0;
}

dfs 函数的最后

    FOR(x, p[t]) {
         f[u][x] += b1[x] + b2[x];
         ans = max(ans, f[u][x]);
    }

写错了,应该是

FOR (x, p[t]) {
  f[u][x] += b1[x];
  ans = max(ans, f[u][x] + b2[x]);
} 

诶,搞不懂我为何如此傻逼。
我看了 palayutm 的 submission,发现我的维护最大和次大的写法实在是太蠢了。实际上这类树上 DP 问题都不必这样写。dfs 函数比较好的写法是

void dfs(int u) {
    vis[u] = true;
    int t = a[u];

    map<int,int> b1, b2;

    FOR(x, p[t]) {
        f[u][x] = 1, ans = max(ans, 1);
    }

    FOR(v, g[u]) {
        if(!vis[v]) {
            dfs(v);
            FOR(x, p[t]) {
                auto iter = f[v].find(x);
                if(iter != f[v].end()) {
                    int tmp = iter->second;
                    ans = max(ans, f[u][v] + tmp);
                    f[u][v] = max(f[u][v], 1 + tmp);
                }
            }
        }
    }
}

另一个应该改进的写法是求 1,2, \dots, n 的质因子。自然是用埃氏筛。质因子放到 std::vector<int> 里。比较紧凑的写法是

// vector<vector<int>> p(N);
rng (i, 2, SZ(p)) if (p[i].empty()) 
    for (int j = i; j < SZ(p); j += i) p[j].pb(i);

相关文章

  • CF1101 D GCD Counting

    犯了一个愚蠢的错误。 在 dfs 函数的最后 写错了,应该是 诶,搞不懂我为何如此傻逼。我看了 palayutm ...

  • iOS - GCD

    目录 GCD简介 GCD核心概念 GCD队列的使用 GCD的常见面试题 GCD简介 Grand Central D...

  • git 的冲突合并

    git pull 之后有冲突: $ git pull remote: Counting objects: 5, d...

  • git 冲突

    git pull 之后有冲突: $ git pull remote: Counting objects: 5, d...

  • GCD随笔

    GCD:grand center dispatch(伟大的中枢调度器),打开GCD的包文件

  • iOS开发之GCD串行队列

    iOS开发多线程之GCDiOS开发之GCD同步任务加强iOS开发之GCD串行队列iOS开发之GCD并发队列 实例d...

  • GCD编程

    今天谈论gcd编程的相关知识,gcd编程应该包涵的知识点有:g c d串行队列和并发队列,g c d的延时,线程组...

  • iOS多线程 基本使用实例

    NSThread GCD GCD 详解:http://www.jianshu.com/p/d1f9b2a7b0a8...

  • 相泽三三生日企划

    counting down 5 电台 counting down 4 围巾 counting down 3 烧酒 ...

  • 优化Swift性能 (Optimizing Swift Perf

    主要从三个方面进行优化: 引用计数(Reference Counting) 泛型(Generics) 动态分发(D...

网友评论

      本文标题:CF1101 D GCD Counting

      本文链接:https://www.haomeiwen.com/subject/ehyqdqtx.html