#include <iostream> #include <vector> #include <functional> using namespace std; const int MOD = 1000000007; int gcd(int a, int b) { while (a && b) if (a < b) b %= a; else a %= b; return a + b; } struct Edge { int a, b, val; }; struct UnionFind { vector<int>parent; UnionFind(int n) { parent.resize(n); for (int i = 0; i < n; i++) parent[i] = i; } int find(int x) { if (parent[x] == x) return x; return parent[x] = find(parent[x]); } void merge(int x, int y) { x = find(x); y = find(y); parent[x] = y; } }; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n; cin >> n; vector<int>A(n); for (int& x : A) cin >> x; vector<Edge>E; for (int i = 1; i < n; i++) for (int j = 0; j < i; j++) E.push_back(Edge{i, j, gcd(A[i], A[j])}); long long result = 0; UnionFind UF(n); function<void(int,int,UnionFind&, long long)> R = [&](int estart, int eleft, UnionFind& uf, long long acc) { int first = -1; for (int eid = estart; eid < (int)E.size() - eleft + 1; eid++) if (uf.find(E[eid].a) != uf.find(E[eid].b)) { if (eleft == 1) result = (result + acc * E[eid].val) % MOD; else if (first == -1) { first = eid; } else { UnionFind new_uf(uf); new_uf.merge(E[eid].a, E[eid].b); R(eid + 1, eleft - 1, new_uf, (acc * E[eid].val) % MOD); } } if (first != -1) { uf.merge(E[first].a, E[first].b); R(first + 1, eleft - 1, uf, (acc * E[first].val) % MOD); } }; R(0, n - 1, UF, 1); cout << result << endl; return 0; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | #include <iostream> #include <vector> #include <functional> using namespace std; const int MOD = 1000000007; int gcd(int a, int b) { while (a && b) if (a < b) b %= a; else a %= b; return a + b; } struct Edge { int a, b, val; }; struct UnionFind { vector<int>parent; UnionFind(int n) { parent.resize(n); for (int i = 0; i < n; i++) parent[i] = i; } int find(int x) { if (parent[x] == x) return x; return parent[x] = find(parent[x]); } void merge(int x, int y) { x = find(x); y = find(y); parent[x] = y; } }; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n; cin >> n; vector<int>A(n); for (int& x : A) cin >> x; vector<Edge>E; for (int i = 1; i < n; i++) for (int j = 0; j < i; j++) E.push_back(Edge{i, j, gcd(A[i], A[j])}); long long result = 0; UnionFind UF(n); function<void(int,int,UnionFind&, long long)> R = [&](int estart, int eleft, UnionFind& uf, long long acc) { int first = -1; for (int eid = estart; eid < (int)E.size() - eleft + 1; eid++) if (uf.find(E[eid].a) != uf.find(E[eid].b)) { if (eleft == 1) result = (result + acc * E[eid].val) % MOD; else if (first == -1) { first = eid; } else { UnionFind new_uf(uf); new_uf.merge(E[eid].a, E[eid].b); R(eid + 1, eleft - 1, new_uf, (acc * E[eid].val) % MOD); } } if (first != -1) { uf.merge(E[first].a, E[first].b); R(first + 1, eleft - 1, uf, (acc * E[first].val) % MOD); } }; R(0, n - 1, UF, 1); cout << result << endl; return 0; } |