一、题目
1、题目描述
2、输入输出
2.1输入
2.2输出
3、原题链接
二、解题报告
1、思路分析
2600的题,不过还算友好
先思考我们最终的答案是什么样的?
a[0] * a[0]的某个因子
而结点的值都在1000以内,所以因子个数不超过32(这个可以打表看一下)
然后dp味还是比较强的
我们先预处理几个数组,gcd[i][j]即 i 和 j 的gcd
divs[i],即 i 的所有因子,降序排序
ceilSqrt[i],即 j ^ 2 = i的最小 j
每个样例预处理一次:
subG[u],即 子树u的gcd
我们从大到小去遍历a[0]的因子,只要有能够在k步以内调整出来的,我们就求答案输出
dfs(u, fa, d) 表示 子树 u 的gcd是否可以调整为 d 的倍数
如果 subG[u] % d == 0,不需要调整,直接返回
如果 subG[u] * subG[u] % d == 0,那么调整一次就能得到
如果 u 为 叶子 或者 a[u] * a[u] % d != 0,那么无法调整,直接返回
否则,看 u 的所有子树 v 是否都能调整出 ceilSqrt[d] 的倍数,如果可以,那么每个子树都可以贡献出ceilSqrt[d],我们再对u 调整一次就能得到d的倍数
详细实现看代码
2、复杂度
时间复杂度: O(32N)空间复杂度:O(32N)
3、代码详解
#include <bits/stdc++.h>
using i64 = long long;
using i128 = __int128;
using PII = std::pair<int, int>;
using PIII = std::pair<int, PII>;
constexpr int inf = 1e9 + 7, P = 1e9 + 7;
constexpr int N = 1000;
std::vector<int> divs[N + 1];
int gcd[N + 1][N + 1];
int ceilSqrt[N + 1];
void init() {
for (int i = N; i; -- i) {
for (int j = i; j <= N; j += i)
divs[j].push_back(i);
for (int j = 1; j <= N; ++ j)
gcd[i][j] = std::gcd(i, j);
ceilSqrt[i] = 1;
int x = i;
for (int p = 2; p * p <= x; ++ p) {
while (x % (p * p) == 0) {
ceilSqrt[i] *= p;
x /= (p * p);
}
if (x % p == 0) {
ceilSqrt[i] *= p;
x /= p;
}
}
if (x > 1)
ceilSqrt[i] *= x;
}
}
void solve() {
int n, k;
std::cin >> n >> k;
std::vector<int> a(n);
for (int i = 0; i < n; ++ i) std::cin >> a[i];
std::vector<std::vector<int>> g(n);
for (int i = 1, u, v; i < n; ++ i) {
std::cin >> u >> v;
-- u, -- v;
g[u].push_back(v), g[v].push_back(u);
}
if (!k) {
std::cout << a[0] << '\n';
return;
}
std::vector<int> subG(n);
auto dfs0 = [&](auto&& self, int u, int fa) -> void {
subG[u] = a[u];
for (int v : g[u])
if (v != fa) {
self(self, v, u);
subG[u] = gcd[subG[u]][subG[v]];
}
};
dfs0(dfs0, 0, -1);
int cnt = 0;
auto dfs = [&](auto&& self, int u, int fa, int d) -> void {
if (subG[u] % d == 0)
return;
if (subG[u] * subG[u] % d == 0) {
++ cnt;
return;
}
if (g[u].size() == 0 || a[u] * a[u] % d) {
cnt = inf;
return;
}
for (int v : g[u])
if (v != fa)
self(self, v, u, ceilSqrt[d]);
++ cnt;
};
for (int d : divs[a[0]]) {
cnt = 0;
for (int v : g[0])
dfs(dfs, v, 0, d);
if (cnt < k) {
std::cout << a[0] * d << '\n';
return;
}
}
}
int main(int argc, char** argv) {
std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
init();
int _ = 1;
std::cin >> _;
while (_ --)
solve();
return 0;
}