数学,结论题
告诉大家一个结论。
求解任意区间的gcd中,gcd的变化最多只有log2(max(num))次
为什么这样说呢?
现在假设我们求解从L到后面任意一个前缀的gcd
我们想想哈,这个gcd值一定是<=a[L]的
我们想想这个gcd的变化,每次变化最小还是得/2那么最多log2(a[L])次
实际上变化的还会更少!!!
那么依据这个理论,我们可以做出这题。
时空复杂度其实是很小的。
#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pll;
const int max_n = 1e5+100;
const ll mod = 1e9+7;
struct edge{
int to,next;
}E[max_n<<1];
int head[max_n];
int cnt=1;
void add(int from,int to){
E[cnt].to=to;
E[cnt].next=head[from];
head[from]=cnt++;
}
ll x[max_n];
int n;
map<ll,ll> mp[max_n];
ll ans=0;
void dfs(int u,int fa){
mp[u][x[u]]++;
for (pll it:mp[fa])mp[u][__gcd(it.first,x[u])]+=it.second;
for (int i=head[u];i;i=E[i].next)
if (E[i].to!=fa)dfs(E[i].to,u);
for (pll it:mp[u])ans = (ans+it.first*it.second)%mod;
}
int main(){
cin>>n;
for (int i=1;i<=n;++i)cin>>x[i];
for (int i=1,u,v;i<n;++i){
cin>>u>>v;
add(u,v);add(v,u);
}dfs(1,0);
cout<<ans<<endl;
}
京公网安备 11010502036488号