#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+5;
int tot,n,m,ver[maxn];
int pos[maxn],pri[maxn],vis[maxn],cnt=0;
struct tt{
int l,r,val;
//素因子出现次数
}tree[maxn<<8];
//线性筛
void init(){
memset(pri,0,sizeof(pri));
memset(vis,0,sizeof(vis));
for(int i=2;i<maxn;i++){
if(!vis[i]){
pri[++cnt]=i;
pos[i]=cnt;
vis[i]=i;
}
for(int j=1;j<=cnt&&pri[j]<=maxn/i;j++){
vis[i*pri[j]]=pri[j]; //vis[x]存x的最小质因子 ,后面while(x>1)要用到
pos[i*pri[j]]=j;
if(i%pri[j]==0) break;
}
}
}
int build(int l,int r){
int rt=++tot;
tree[rt].val=0;
tree[rt].l=rt;
tree[rt].r=rt;
return rt;
}
void pushup(int root){
tree[root].val=tree[tree[root].l].val+tree[tree[root].r].val;
}
int change(int node,int l,int r,int pos,int val){
int root=++tot;
tt &rt=tree[root];
rt=tree[node];
if(l==r){
rt.val+=val;
return root;
}
int mid=(l+r)>>1;
if(pos<=mid) rt.l=change(rt.l,l,mid,pos,val);
else rt.r=change(rt.r,mid+1,r,pos,val);
pushup(root);
return root;
}
int query(int per,int lst,int l,int r,int p){
tt &pp=tree[per],&ll=tree[lst];
if(l==r)
return ll.val-pp.val;
//找到叶子结点(即质因子),就返回该质因子出现的次数
int mid=(l+r)>>1;
if(p<=mid) return query(pp.l,ll.l,l,mid,p);
else return query(pp.r,ll.r,mid+1,r,p);
}
int main(){
int t,l,r,x,y,z,p,ok;
init();
cin>>t;
while(t--){
scanf("%d%d",&n,&m);
tot=0;
memset(ver,0,sizeof(ver));
//树建的是质因子的是,所以是cnt(质因子的个数),不是n
ver[0]=build(1,cnt);
for(int i=1;i<=n;i++){
scanf("%d",&x);
ver[i]=ver[i-1];//x为1时,没有质数不进while就没变,所以要先=前一个
while(x>1){
y=0,z=vis[x],p=pos[x];
while(x%z==0) ++y,x/=z;
ver[i]=change(ver[i],1,cnt,p,y);
//p是质因子的位置,y是这个质因子出现的次数
}
}
for(int i=1;i<=m;i++){
scanf("%d%d%d",&l,&r,&x);
ok=1;
while(x>1){
y=0,z=vis[x],p=pos[x];
//p是第几个质因子
while(x%z==0) ++y,x/=z;
//如果分母的该质因子次数> 分子的该质因子次数。就不能整除,就ok置0(即错)退出
if(y>query(ver[l-1],ver[r],1,cnt,p))
ok=0,x=1;
}
//结束是ok仍为1,说明分子包含了分母的各个质因子,则yes
if(ok) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
}
return 0;
}
hdu6287可持久线段树+线性筛
猜你喜欢
转载自blog.csdn.net/weixin_50904510/article/details/120047864
今日推荐
周排行