题意:给N个数,有M个查询,问区间[L,R]之间有多少个数与这个区间内的其他数都互质。
易得,一个区间内的数的个数减去,与其他数不互质的数即可——即离当前数i左边最近的不互质的数的位置(设为L[i])和右边最近的不互质的数的位置(设为R[i])有一个在区间[L,R]内。那么问题就变成统计:1.区间[L,R]中有多少个数的L[i]或R[i]在区间[L,R]内。2.多少个数的L[i]且R[i]在区间[L,R]内。对于每个询问,答案就是区间内的数减去1的结果,再加上2的结果。
2的结果其实就是询问有多少个区间[L[i],R[i]]完全在给定区间[L,R]内。其实1也可以转化为相同的问题,即区间[L[i],i]或[R[i],i],是否在给定区间内。
对于问有多少个区间是在给定的区间内,可以直接离线搞。
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <algorithm>
#include <stdlib.h>
#include <string>
#include <queue>
#include <map>
#include <vector>
#include <set>
#define maxn 1000010
#define oo 1000000000
#define clearAll(a) memset(a,0,sizeof(a))
#define sq(a) ((a)*(a))
#define LL(x) (x<<1)
#define RR(x) (x<<1|1)
#define MID(a,b) (a+((b-a)>>1))
using namespace std;
typedef long long ll;
const int N=200015;
struct Range
{
int st,ed,ind;
Range(){}
Range(int st,int ed,int ind) :
st(st),ed(ed),ind(ind) {}
bool operator<(const Range &B)const
{
return ed<B.ed;
}
};
int n,m,mx;
int A[N],L[N],R[N],pos[N];
int ans[3][N],num[N];
vector<Range>rab[3],range;
void fun(bool flag)
{
if(flag==0)
{
for(int i=0;i<=mx;i++) pos[i]=0;
for(int i=1;i<=n;i++)
{
int tmp=A[i];
for(int j=2;j*j<=tmp;j++)
{
if(tmp%j) continue;
L[i]=max(L[i],pos[j]);
pos[j]=i;
while(tmp%j==0) tmp/=j;
}
if(tmp!=1)
{
L[i]=max(L[i],pos[tmp]);
pos[tmp]=i;
}
}
}
else
{
for(int i=0;i<=mx;i++) pos[i]=n+1;
for(int i=n;i>=1;i--)
{
int tmp=A[i];
for(int j=2;j*j<=tmp;j++)
{
if(tmp%j) continue;
R[i]=min(R[i],pos[j]);
pos[j]=i;
while(tmp%j==0) tmp/=j;
}
if(tmp!=1)
{
R[i]=min(R[i],pos[tmp]);
pos[tmp]=i;
}
}
}
}
struct BIT
{
int T[N];
void clear() { for(int i=1;i<=n+10;i++) T[i]=0; }
int lowbit(int x) { return x&(-x); }
void updata(int pos)
{
if(pos==0||pos==n+1) return;
for(int i=pos;i<=n;i+=lowbit(i)) T[i]++;
}
int query(int st,int ed)
{
int ans=0;
for(int i=ed;i>=1;i-=lowbit(i)) ans+=T[i];
for(int i=st-1;i>=1;i-=lowbit(i)) ans-=T[i];
return ans;
}
}seg;
void getAns(int key)
{
seg.clear();
int ind=0;
for(int i=0;i<m;i++)
{
int st=range[i].st;
int ed=range[i].ed;
int id=range[i].ind;
while(ind<n&&rab[key][ind].ed<=ed)
{
seg.updata(rab[key][ind].st);
ind++;
}
ans[key][id]+=seg.query(st,ed);
}
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
if(n==0&&m==0) break;
range.clear(); mx=0;
rab[0].clear(); rab[1].clear(); rab[2].clear();
for(int i=0;i<N;i++)
{
L[i]=0; R[i]=n+1;
ans[0][i]=ans[1][i]=ans[2][i]=0;
}
for(int i=1;i<=n;i++)
{
scanf("%d",&A[i]);
mx=max(mx,A[i]);
}
for(int i=0;i<m;i++)
{
int x,y; scanf("%d%d",&x,&y);
num[i]=y-x+1;
range.push_back(Range(x,y,i));
}
fun(0); fun(1);
for(int i=1;i<=n;i++)
{
rab[0].push_back(Range(L[i],i,0));
rab[1].push_back(Range(i,R[i],0));
rab[2].push_back(Range(L[i],R[i],0));
}
sort(range.begin(),range.end());
sort(rab[0].begin(),rab[0].end());
sort(rab[1].begin(),rab[1].end());
sort(rab[2].begin(),rab[2].end());
getAns(0);
getAns(1);
getAns(2);
for(int i=0;i<m;i++) printf("%d\n",num[i]-ans[0][i]-ans[1][i]+ans[2][i]);
}
return 0;
}