题意:已给数列,给定一个区间,求区间内的某个数x可以整除区间内所有值,求此x的个数
显然个数就是区间内gcd(al,al+1,al+2,...,ar-1,ar)的个数
求任何区间的gcd,可以用线段树解决
求任何区间内某个数的个数可以:先用pair记录值和index,再排序用二分确定上下界,单次复杂度是Ologn
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
#define root 1,n,1
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int N = 1e5+100;
typedef pair<int,int >pii;
int d[N<<2];
int a[N];
pii b[N];
int gcd(int a,int b)
{
if(b==0) return a;
else return gcd(b,a%b);
}
void pushup(int rt)
{
d[rt]=gcd(d[rt<<1],d[rt<<1|1]);
}
void build(int l,int r,int rt)
{
if(l==r) {d[rt]=a[l];return;}
int m=(l+r)>>1;
build(lson);
build(rson);
pushup(rt);
}
int query(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R) return d[rt];
int m=(l+r)>>1;
int x,y;
x=y=0;
if(L<=m) x=query(L,R,lson);
if(R>m) y=query(L,R,rson);
return gcd(x,y);
}
int main()
{
int n,t;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i],b[i].first=a[i],b[i].second=i;
build(root);
sort(b+1,b+1+n);
cin>>t;
for(int i=1;i<=t;i++)
{
int l,r;
scanf("%d%d",&l,&r);
int gd=query(l,r,root);
int fr=lower_bound(b+1,b+n+1,pii(gd,l))-(b+1);
int ba=lower_bound(b+1,b+1+n,pii(gd,r+1))-(b+1);
printf("%d\n",(r-l+1)-(ba-fr));
}
}