http://acm.hdu.edu.cn/showproblem.php?pid=6287
记录每一个质数存在的下标,比如数据 2 4 8 16 那么v[2]={1,2,2,3,3,3,4,4,4,4}; 表示2这个质数在数据中出现的下标。用vector可以实现。查询之前先处理好每个质数的数组 那么查询[l,r]=[2,4]中, 有2的多少次方: upper_bound(v[2].begin(),v[2].end(),r)-lower_bound(v[2].begin(),v[2].end(),l) 答案是9,表示l到r之间最多能够组成2的9次方; 对查询中的数d进行质因数分解,再逐个质因数进行查询即可解决。 对某个数进行质因数分解时,分解过程中若a为质数,则跳出循环,不然会卡时间
typedef long long ll; typedef pair<int,int> P; int n,m,a,l,r,d; vector<int>v[100005]; int p[100005],np[100005],pcnt; void primediv(int n){ memset(np,0,sizeof np);pcnt=0; for(int i=2;i<=n;i++){ if(np[i]==0){ p[pcnt++]=i; } for(int j=0;j<pcnt && p[j]*i<=n;j++){ np[p[j]*i]=1; if(i%p[j]==0)break; } } } void resolve(int a, int k){ for(int i=0;np[a];i++){ while(a%p[i]==0){ v[p[i]].push_back(k); a/=p[i]; } } if(a>1)v[a].push_back(k);//important! } int main(){ primediv(100001); int t; scanf("%d",&t); while(t--){ for(int i=0;i<pcnt;i++)v[p[i]].clear(); scanf("%d %d",&n,&m); for(int i=1;i<=n;i++){ scanf("%d",&a); resolve(a,i); } while(m--){ scanf("%d %d %d",&l,&r,&d); int flag=1; for(int i=0, num=0;np[d] && flag;i++){ while(d%p[i]==0) d/=p[i],num++; if(num){ int cnt=upper_bound(v[p[i]].begin(),v[p[i]].end(),r) -lower_bound(v[p[i]].begin(),v[p[i]].end(),l); if(cnt<num)flag=0; num=0; } } if(flag && d>1){//important int cnt=upper_bound(v[d].begin(),v[d].end(),r) -lower_bound(v[d].begin(),v[d].end(),l); if(cnt<1)flag=0; } if(flag)printf("Yes\n"); else printf("No\n"); } } return 0; }