题目
题意:
有n个数字,m个查询,每次询问[l,r]这些数字中,和其他数都互质的数有多少个。
题解:
从左到右遍历,对每个数因子分解,如果它含有的因子在之前也有数含有,那么便可知那个数和它不互质,所以可以求出每个数i左边第一个和它不互质的数的位置,记为lefi,右边同理,记为rigi。
然后将查询按l排序,从左往右遍历原数组,遍历到j时,若存在i使得j-1=lefi,则可知从j到(rigi)-1都和i互质,因此如果有查询的l=j,而r=[i,rigi)的话,这个区间里i是一个满足要求的数。这里可以用线段树或者树状数组。
代码:
//Time:1843ms //Memory:9216KB //Length:2574B #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define MP(x,y) make_pair(x,y) #define FI first #define SE second const int MAXN = 200010; int tree[MAXN]; int pri[MAXN],ptop,yin[MAXN]; int arr[MAXN],pre[MAXN],ans[MAXN],bel[MAXN]; pair<int,int> pa[MAXN]; bool vi[MAXN]; struct _query { int l,r,id; bool operator < (const _query &b) const { return l<b.l; } }que[MAXN]; void cal(int n) { memset(yin,-1,sizeof(yin)); for(int i=0;i<n;++i) { int pos=-1,tmp=arr[i]; for(int j=0;(long long)pri[j]*pri[j]<=tmp;++j) if(tmp%pri[j]==0) { pos=max(pos,yin[j]); yin[j]=i; while(tmp%pri[j]==0) tmp/=pri[j]; } if(tmp>1) { pos=max(pos,yin[bel[tmp]]); yin[bel[tmp]]=i; } pre[i]=pos+1; } } void add(int h,int num) { ++h; while(h<MAXN) { tree[h]+=num; h+=h&(-h); } } int query(int h) { ++h; int cnt=0; while(h) { cnt+=tree[h]; h-=h&(-h); } return cnt; } int main() { //freopen("/home/moor/Code/input","r",stdin); int n,m,ql,pl; ptop=0; memset(vi,0,sizeof(vi)); for(int i=2;i<MAXN;++i) if(!vi[i]) { bel[i]=ptop; pri[ptop++]=i; for(int j=i;j<MAXN;j+=i) vi[j]=1; } while(scanf("%d%d",&n,&m)==2&&n) { for(int i=0;i<n;++i) scanf("%d",&arr[i]); cal(n); for(int i=0;i<n;++i) pa[i]=MP(pre[i],i); sort(pa,pa+n); for(int i=0,j=n-1;i<j;++i,--j) swap(arr[i],arr[j]); cal(n); for(int i=0;i<n;++i) pre[i]=n-1-pre[i]; for(int i=0,j=n-1;i<j;++i,--j) swap(arr[i],arr[j]),swap(pre[i],pre[j]); for(int i=0;i<m;++i) scanf("%d%d",&que[i].l,&que[i].r),que[i].id=i,--que[i].l,--que[i].r; sort(que,que+m); ql=0,pl=0; memset(tree,0,sizeof(tree)); for(int i=0;i<n;++i) { if(i) { add(pre[i-1]+1,1); add(i-1,-1); } while(pl<n&&pa[pl].FI==i) { add(pa[pl].SE,1); add(pre[pa[pl].SE]+1,-1); ++pl; } while(ql<m&&que[ql].l==i) { ans[que[ql].id]=query(que[ql].r); ++ql; } } for(int i=0;i<m;++i) printf("%d\n",ans[i]); } return 0; }