6287
可持久化线段树+线性筛
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int n,m,tot=-1,ver[maxn];
int su[maxn],pos[maxn],vis[maxn],ans=0;//ans素数个数 ,素数表,序号,最大的
struct treenode{
int l,r;
int tim;//素因子出现次数
}tree[maxn<<9];
//素数表 ,利用线性筛
void init(){
memset(su,0,sizeof(su));
memset(vis,0,sizeof(vis));
for(int i=2;i<=maxn;i++){
if(!vis[i])su[++ans]=i,vis[i]=i,pos[i]=ans;
for(int j=1;j<=ans;j++){
if(i*su[j]>=maxn||su[j]>vis[i])break;
vis[i*su[j]]=su[j],pos[i*su[j]]=j;
}
}
}
int build(int l,int r){
int root=++tot;
tree[root].l=0;
tree[root].r=root;
tree[root].tim=root;
return root;
}
int update(int node,int l,int r,int p,int val){
int root=++tot;
treenode &rt=tree[root];
rt=tree[node];
if(l==r){
rt.tim+=val;
return root;
}
int mid=(l+r)>>1;
if(p<=mid)rt.l=update(rt.l,l,mid,p,val);
else rt.r=update(rt.r,mid+1,r,p,val);
rt.tim=tree[rt.l].tim+tree[rt.r].tim;
return root;
}
int query(int now,int lst,int l,int r,int p){
treenode &t1=tree[now],&t2=tree[lst];
if(l==r)return t1.tim-t2.tim;//找到这个质因子并返回出现的次数
int mid=(l+r)>>1;
if(p<=mid)return query(t2.l,t1.l,l,mid,p);
else query(t2.r,t1.r,mid+1,r,p);
}
//因为是判断答案是否正确的题目,所以相似的结构会重复出现表示检验
//主要思想是通过判断在这个数据中出现的质因子的种类个数来判断答案
int main(){
int t,a,b,c,p,l,r,x,y,z,flag;
scanf("%d",&t);
init();
while(t--){
scanf("%d%d",&n,&m);
memset(ver,0,sizeof(ver));
ver[0]=build(1,ans);
for(int i=1;i<=n;i++){
ver[i]=ver[i-1];//输入数据为1时,不进循环
scanf("%d",&a);
while(a>1){
b=0,c=vis[a],p=pos[a];
while(a%c==0)++b,a=a/c;
ver[i]=update(ver[i],1,ans,p,b);//p是质因子,b是出现次数
}
}
for(int i=1;i<=m;i++){
scanf("%d%d%d",&l,&r,&x);
flag=1;
while(x>1){
y=0,z=vis[x],p=pos[x];
while(x%z==0)++y,x=x/z;
if(y>query(ver[l-1],ver[r],1,ans,p))flag=0,x=1;
}
printf("%s\n",flag?"Yes":"No");
}
}
return 0;
}