159 lines
3.4 KiB
C++
159 lines
3.4 KiB
C++
|
#include <algorithm>
|
|||
|
#include <cmath>
|
|||
|
#include <unordered_map>
|
|||
|
#include <vector>
|
|||
|
|
|||
|
namespace {
|
|||
|
struct factors_iterator {
|
|||
|
factors_iterator() : f(-1) {}
|
|||
|
factors_iterator(int f, int n) : f(f), n(n), upper(std::sqrt(n)) {}
|
|||
|
|
|||
|
auto operator!=(const factors_iterator &other) const -> bool {
|
|||
|
return f != other.f;
|
|||
|
}
|
|||
|
|
|||
|
auto operator*() const -> int { return f; }
|
|||
|
|
|||
|
auto operator++() -> factors_iterator & {
|
|||
|
// ‹f› yielded a prime
|
|||
|
if (f > upper || n == 1) {
|
|||
|
f = -1;
|
|||
|
return *this;
|
|||
|
}
|
|||
|
|
|||
|
do {
|
|||
|
++f;
|
|||
|
} while (f <= upper && n % f != 0);
|
|||
|
|
|||
|
// ‹n› is a prime
|
|||
|
if (f > upper) {
|
|||
|
f = n;
|
|||
|
}
|
|||
|
|
|||
|
while (n % f == 0) {
|
|||
|
n /= f;
|
|||
|
}
|
|||
|
|
|||
|
return *this;
|
|||
|
}
|
|||
|
|
|||
|
private:
|
|||
|
int f;
|
|||
|
int n;
|
|||
|
int upper;
|
|||
|
};
|
|||
|
|
|||
|
struct factors {
|
|||
|
factors(int n) : n(n) {}
|
|||
|
auto begin() const -> factors_iterator { return ++factors_iterator(1, n); }
|
|||
|
auto end() const -> factors_iterator { return factors_iterator(); }
|
|||
|
|
|||
|
private:
|
|||
|
int n;
|
|||
|
};
|
|||
|
|
|||
|
void dfs(std::unordered_map<int, std::vector<int>> &graph,
|
|||
|
std::vector<bool> &visited, int u) {
|
|||
|
visited[u] = true;
|
|||
|
for (auto v : graph[u]) {
|
|||
|
if (!visited[v]) {
|
|||
|
dfs(graph, visited, v);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
} // namespace
|
|||
|
|
|||
|
class Solution {
|
|||
|
public:
|
|||
|
bool canTraverseAllPairs(const std::vector<int> &nums) {
|
|||
|
auto n = nums.size();
|
|||
|
|
|||
|
std::unordered_map<int, int> gcd;
|
|||
|
std::unordered_map<int, std::vector<int>> neighbors;
|
|||
|
|
|||
|
for (auto i = 0u; i < n; ++i) {
|
|||
|
for (auto f : factors(nums[i])) {
|
|||
|
if (gcd.contains(f)) {
|
|||
|
int u = i;
|
|||
|
int v = gcd[f];
|
|||
|
neighbors[u].push_back(v);
|
|||
|
neighbors[v].push_back(u);
|
|||
|
}
|
|||
|
|
|||
|
gcd[f] = i;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
std::vector<bool> visited(n, false);
|
|||
|
dfs(neighbors, visited, 0);
|
|||
|
|
|||
|
return std::find(visited.begin(), visited.end(), false) ==
|
|||
|
visited.end();
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
#ifdef _MF_TEST
|
|||
|
#include <gtest/gtest.h>
|
|||
|
|
|||
|
TEST(examples, no_1) {
|
|||
|
Solution s;
|
|||
|
EXPECT_TRUE(s.canTraverseAllPairs(std::vector{2, 3, 6}));
|
|||
|
}
|
|||
|
TEST(examples, no_2) {
|
|||
|
Solution s;
|
|||
|
EXPECT_FALSE(s.canTraverseAllPairs(std::vector{3, 9, 5}));
|
|||
|
}
|
|||
|
TEST(examples, no_3) {
|
|||
|
Solution s;
|
|||
|
EXPECT_TRUE(s.canTraverseAllPairs(std::vector{4, 3, 12, 8}));
|
|||
|
}
|
|||
|
|
|||
|
TEST(factors, prime_2) {
|
|||
|
std::vector<int> fs;
|
|||
|
for (auto f : factors(2)) {
|
|||
|
fs.push_back(f);
|
|||
|
}
|
|||
|
EXPECT_EQ(fs, std::vector{2});
|
|||
|
}
|
|||
|
TEST(factors, prime_7) {
|
|||
|
std::vector<int> fs;
|
|||
|
for (auto f : factors(7)) {
|
|||
|
fs.push_back(f);
|
|||
|
}
|
|||
|
EXPECT_EQ(fs, std::vector{7});
|
|||
|
}
|
|||
|
TEST(factors, prime_29) {
|
|||
|
std::vector<int> fs;
|
|||
|
for (auto f : factors(29)) {
|
|||
|
fs.push_back(f);
|
|||
|
}
|
|||
|
EXPECT_EQ(fs, std::vector{29});
|
|||
|
}
|
|||
|
TEST(factors, composite_6) {
|
|||
|
std::vector<int> fs;
|
|||
|
for (auto f : factors(6)) {
|
|||
|
fs.push_back(f);
|
|||
|
}
|
|||
|
EXPECT_EQ(fs, (std::vector{2, 3}));
|
|||
|
}
|
|||
|
TEST(factors, composite_15) {
|
|||
|
std::vector<int> fs;
|
|||
|
for (auto f : factors(15)) {
|
|||
|
fs.push_back(f);
|
|||
|
}
|
|||
|
EXPECT_EQ(fs, (std::vector{3, 5}));
|
|||
|
}
|
|||
|
TEST(factors, composite_1024) {
|
|||
|
std::vector<int> fs;
|
|||
|
for (auto f : factors(1024)) {
|
|||
|
fs.push_back(f);
|
|||
|
}
|
|||
|
EXPECT_EQ(fs, std::vector{2});
|
|||
|
}
|
|||
|
|
|||
|
int main(int argc, char **argv) {
|
|||
|
testing::InitGoogleTest(&argc, argv);
|
|||
|
return RUN_ALL_TESTS();
|
|||
|
}
|
|||
|
#endif
|