这个题目要用到一个结论,就是区间一个区间长度为n的不同的gcd不会超过logn 个,
其实就是知道这个题目可以暴力就好了。
然后就是对于每一个节点,我都存从祖先到这个节点的所有的gcd,用一个vector存下来。
然后因为这个vector的size 不会很大,所以就可以直接暴力往下转移。
#include <cstdio> #include <cstring> #include <cstdlib> #include <queue> #include <bitset> #include <string> #include <algorithm> #include <iostream> #include <map> #define inf 0x3f3f3f3f #define inf64 0x3f3f3f3f3f3f3f3f using namespace std; const int maxn = 1e5 + 10; const int mod = 1e9 + 7; typedef long long ll; typedef pair<ll, ll> P; vector<P>val[maxn]; vector<int>G[maxn]; ll a[maxn], ans; void add(int u, int v) { G[u].push_back(v); G[v].push_back(u); } ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a%b); } void dfs(int u, int pre,int dep) { for (int i = 0; i < G[u].size(); i++) { int v = G[u][i]; if (v == pre) continue; for (int j = 0; j < val[u].size(); j++) { P now = val[u][j]; ll ans = gcd(now.first, a[v]); int len = val[v].size(); if (len == 0 || ans != val[v][len - 1].first) val[v].push_back(make_pair(ans, now.second)); } val[v].push_back(make_pair(a[v], dep + 1)); dfs(v, u, dep + 1); } } void dfs1(int u, int pre) { for (int i = 1; i < val[u].size(); i++) { ans += (val[u][i].second - val[u][i - 1].second) % mod*val[u][i - 1].first%mod; ans %= mod; } ans += a[u] % mod; ans %= mod; for (int i = 0; i < G[u].size(); i++) { int v = G[u][i]; if (v == pre) continue; dfs1(v, u); } } /* void dfsprint(int u, int pre) { for (int i = 0; i < val[u].size(); i++) { printf("ww u=%d %lld %lld\n", u, val[u][i].first, val[u][i].second); } for (int i = 0; i < G[u].size(); i++) { int v = G[u][i]; if (v == pre) continue; dfsprint(v, u); } } */ int main() { int n; scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%lld", &a[i]); for (int i = 1; i < n; i++) { int u, v; scanf("%d%d", &u, &v); add(u, v); } val[1].push_back(make_pair(a[1], 1)); dfs(1, -1, 1); ans = 0; dfs1(1, -1); // dfsprint(1, -1); printf("%lld\n", ans); return 0; }