解题思路:写了两个小时才写出来,代码能力还有待加强。这道题一开始使用ST表进行维护,用于查询区间范围内的gcd值。但是莫队算法移动一格还有很多区间gcd累加的,要是一个个加必定超时。但是我们可以看出在一定范围内有不少区间的gcd值是一样的,不必一个个数,所以用二分搜索的方式查找,复杂度为O(logn)。我一开始没有事先记录下vl和vr(相同节点),而是要用的时候再查询,这样,复杂度就变成O(log^2n)了,再加上莫队算法的复杂度,就是O(n*sqrt(n)*log^2n),就超时了。但是如果事先用vl,vr记入下来,复杂度就是O(max(n*sqrt(n)*logn , n*log^2(n))),复杂度较之前面小了。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<vector>
#define N 10008
using namespace std;
struct node
{
int l,r,id;
}q[N];
int s[N],be[N];
long long ans,res[N];
vector<pair<int,int> > vl[N],vr[N];
int l1,r1,n;
int p[N][18];
bool cmp(node a,node b)
{
if(be[a.l]==be[b.l]) return a.r<b.r;
return a.l<b.l;
}
int gcd(int a,int b)
{
if(b==0) return a;
return gcd(b,a%b);
}
void build_st()
{
for(int i=1;i<=n;i++) p[i][0]=s[i];//必须从1开始,代表第一位
for(int j=1;j<=17;j++)
{
for(int i=1;i+(1<<j)-1<=n;i++)
{
p[i][j]=gcd(p[i][j-1],p[i+(1<<(j-1))][j-1]);
}
}
}
int query(int l,int r)
{
int k=log2(r-l+1);
return gcd(p[l][k],p[r-(1<<k)+1][k]);
}
int schl(int l,int r)
{
int t=query(l1,l),mid;
int as=l;
while(r>=l)
{
mid=(l+r)/2;
if(query(l1,mid)!=t)
{
r=mid-1;
}else
{
l=mid+1;
as=max(as,mid);
}
}
return as;
}
int schr(int l,int r)
{
int t=query(r,r1),mid;
int as=r;
while(r>=l)
{
mid=(l+r)/2;
if(query(mid,r1)!=t)
{
l=mid+1;
}else
{
r=mid-1;
as=min(as,mid);
}
}
return as;
}
void addl(int l,int r)
{
int l1=l;
for(int i=0;i<vl[l1].size();i++)
{
ans+=(long long)(min(r,vl[l1][i].first)-l+1)*vl[l1][i].second;
l=vl[l1][i].first+1;
if(vl[l1][i].first>=r) break;
}
}
void dell(int l,int r)
{
int l1=l;
for(int i=0;i<vl[l1].size();i++)
{
ans-=(long long)(min(r,vl[l1][i].first)-l+1)*vl[l1][i].second;
l=vl[l1][i].first+1;
if(vl[l1][i].first>=r) break;
}
}
void addr(int l,int r)
{
int r1=r;
for(int i=0;i<vr[r1].size();i++)
{
ans+=(long long)(r-max(l,vr[r1][i].first)+1)*vr[r1][i].second;
r=vr[r1][i].first-1;
if(vr[r1][i].first<=l) break;
}
}
void delr(int l,int r)
{
int r1=r;
for(int i=0;i<vr[r1].size();i++)
{
ans-=(long long)(r-max(l,vr[r1][i].first)+1)*vr[r1][i].second;
r=vr[r1][i].first-1;
if(vr[r1][i].first<=l) break;
}
}
int main()
{
//freopen("t.txt","r",stdin);
int m,T,bck;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
bck=sqrt(n);
for(int i=1;i<=n;i++)
{
scanf("%d",&s[i]);
be[i]=i/bck+1;
}
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&q[i].l,&q[i].r);
q[i].id=i;
}
build_st();
for(int i=n;i>=1;i--)
{
vr[i].clear();
int r=i,l=1;
r1=i;
while(r>=l)
{
int t=schr(l,r);
vr[i].push_back(make_pair(t,query(t,i)));
r=t-1;
}
}
for(int i=1;i<=n;i++)
{
vl[i].clear();
int r=n,l=i;
l1=i;
while(r>=l)
{
int t=schl(l,r);
vl[i].push_back(make_pair(t,query(i,t)));
l=t+1;
}
}
sort(q+1,q+1+m,cmp);
int l=1,r=0;
ans=0;
for(int i=1;i<=m;i++)
{
//cout<<q[i].l<<" "<<q[i].r<<"*"<<endl;
while(l>q[i].l) addl(l-1,r),l--;
while(r<q[i].r) addr(l,r+1),r++;
while(l<q[i].l) dell(l,r),l++;
while(r>q[i].r) delr(l,r),r--;
res[q[i].id]=ans;
}
for(int i=1;i<=m;i++) printf("%lld\n",res[i]);
}
return 0;
}