这道题让我感慨万分啊。一中群里一帮大佬讨论此题无果,问A队爷szb,他说是主席树(可能是对的,反正我不会写),最终被小学生——hzy,A出来了。
题目
#题解:
前缀和维护每个质因数出现个数,到根号n就行,剩下的最多还剩一个,用vector存储。最后在查询时二分判断[l,r]中是否有k这个质因数即可
说实话,这题并不难,但我没想到这么高的时间复杂度竟然能过,理论上有一个多亿了
时间复杂度O(T70(350内质数个数)(n+m))
#标程:
#include<bits/stdc++.h>
using namespace std;
const int N=100002,M=352;
int i,j,T,n,m,k,l,r,sum,s[N][M],vis[M],p[M],cnt,fl;
vector<int>v[N];
int read(){
char c;int x=0,f=1;
do{c=getchar();if(c=='-')f=-1;}while(c<48||c>57);
do x=(x<<1)+(x<<3)+(c^48),c=getchar();while(c>=48&&c<=57);
return f*x;
}
int main(){
for (i=2;i<M;i++)
if (!vis[i]){
p[cnt++]=i;
for (j=i<<1;j<M;j+=i) vis[j]=1;
}
T=read();
while (T--){
n=read();m=read();
for (i=p[cnt-1]+1;i<N;i++) v[i].clear();
memset(s[0],0,sizeof(s[0]));
for (i=1;i<=n;i++){
k=read();
for (j=0;j<cnt;j++){
s[i][j]=s[i-1][j];
while (k%p[j]==0) k/=p[j],s[i][j]++;
}
if (k>1) v[k].push_back(i);
}
while (m--){
l=read();r=read();k=read();
fl=1;
for (i=0;i<cnt;i++){
sum=0;
while (k%p[i]==0) k/=p[i],sum++;
if (sum>s[r][i]-s[l-1][i]){
fl=0;
break;
}
}
printf("%s\n",(!fl || k>1 && lower_bound(v[k].begin(),v[k].end(),l)
==upper_bound(v[k].begin(),v[k].end(),r))?"No":"Yes");
}
}
}