点击打开链接链接
Given a sequence of integers a1, ..., an and q queries x1, ..., xq on it. For each query xi you have to count the number of pairs (l, r)such that 1 ≤ l ≤ r ≤ n and gcd(al, al + 1, ..., ar) = xi.
is a greatest common divisor of v1, v2, ..., vn, that is equal to a largest positive integer that divides all vi.
The first line of the input contains integer n, (1 ≤ n ≤ 105), denoting the length of the sequence. The next line contains n space separated integers a1, ..., an, (1 ≤ ai ≤ 109).
The third line of the input contains integer q, (1 ≤ q ≤ 3 × 105), denoting the number of queries. Then follows q lines, each contain an integer xi, (1 ≤ xi ≤ 109).
For each query print the result in a separate line.
3 2 6 3 5 1 2 3 4 6
1 2 2 0 1
7 10 20 3 15 1000 60 16 10 1 2 3 4 5 6 10 20 60 1000
14 0 2 2 2 0 2 2 1 1
问有几对l r使得从l到r的gcd为x
用线段树会T
ST表 然后二分
代码如下
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#define MAXN 111111
using namespace std;
int n,stgcd[MAXN][35],num[MAXN];
int prelog2[MAXN];
map<int ,long long > ans;
int gcd(int a,int b){
if(b==0)
return a;
return gcd(b,a%b);
}
void init(){
prelog2[1]=0;
for(int i=2;i<=n;i++){
prelog2[i]=prelog2[i-1];
if((1<<prelog2[i]+1)==i)
prelog2[i]++;
}
for(int i=n;i>=1;i--){
stgcd[i][0]=num[i];
for(int j=1;(i+(1<<j)-1)<=n;j++){
stgcd[i][j]=gcd(stgcd[i][j-1],stgcd[i+(1<<j-1)][j-1]);
}
}
}
int getgcd(int l,int r){
int len=r-l+1;
return gcd(stgcd[l][prelog2[len]],stgcd[r-(1<<prelog2[len])+1][prelog2[len]]);
}
void solve(){
for(int i=1;i<=n;i++){
int ed=i,l,r,m,pos;
while(ed<=n){
int xx=getgcd(i,ed);
l=ed,r=n,pos=-1;
while(l<=r){
if(r-l<=1){
if(getgcd(i,r)==xx)
pos=r;
else if(getgcd(i,l)==xx)
pos=l;
break;
}
m=l+r>>1;
if(getgcd(i,m)==xx)
l=m;
else r=m;
}
ans[xx]+=pos-ed+1;
ed=pos+1;
}
}
}
int main(){
int q,xx;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&num[i]);
init();
solve();
scanf("%d",&q);
while(q--){
scanf("%d",&xx);
printf("%I64d\n",ans[xx]);
}
return 0;
}