CF1101D GCD Counting
阿新 • • 發佈:2019-01-13
oid 點分治 比賽 urn sig pac max cto gcd
題目地址:洛谷CF1101D
zz的我比賽時以為是樹剖或者點分治然後果斷放棄了
這道題不能順著做,而應該從答案入手反著想
由於一個數的質因子實在太少了,因此首先找到每個點的點權的所有質因子
進行一次樹形dp,每次更新暴力枚舉所有質因子即可
代碼:
#include <bits/stdc++.h> using namespace std; const int N = 200006; int n, ans = 1; vector<int> p[N], c[N], e[N]; bool flag = 1, v[N]; inline void update(int x, int y) { for (unsigned int i = 0; i < p[x].size(); i++) for (unsigned int j = 0; j < p[y].size(); j++) if (p[x][i] == p[y][j]) { ans = max(ans, c[x][i] + c[y][j]); c[x][i] = max(c[x][i], c[y][j] + 1); } } void dp(int x) { v[x] = 1; for (unsigned int i = 0; i < e[x].size(); i++) { int y = e[x][i]; if (v[y]) continue; dp(y); update(x, y); } } inline void divide(int x, int t) { for (int i = 2; i * i <= x; i++) if (x % i == 0) { p[t].push_back(i); c[t].push_back(1); while (x % i == 0) x /= i; } if (x > 1) { p[t].push_back(x); c[t].push_back(1); } } int main() { cin >> n; for (int i = 1; i <= n; i++) { int x; scanf("%d", &x); divide(x, i); if (x != 1) flag = 0; } if (flag) { puts("0"); return 0; } for (int i = 1; i < n; i++) { int x, y; scanf("%d %d", &x, &y); e[x].push_back(y); e[y].push_back(x); } dp(1); cout << ans << endl; return 0; }
CF1101D GCD Counting