BZOJ5358: [Lydsy1805月赛]口算训练
题解:判断d是否整除,可以转化为求这段区间内d的因子的指数是否均大于d中的指数。容易想到把每个数字都分解为素因子形式,对每个素数出现的次数求个前缀和即可。然而,这样时间空间都不行。注意到对于一个数x,小于sqrt(x)的素因子最多sqrt(x)个,而每个数包含大于sqrt(x)的素因子最多一个。那么容易想到,对于小于sqrt(x)的素因子预处理指数项前缀和。大于sqrt(n)的数,提前分离出来,只需实现区间查询一个数是否出现即可。这个操作,直接分块预处理一下就好了。复杂度o(n×sqrt(n))(大概一辈子都是签到选手了吧。
#include <cstdio> #include <algorithm> #include <cstring> #include <cmath> #include <set> #define mem(MW) memset(MW,0,sizeof(MW)) #define rep(i,a,b) for(int i=a;i<=b;++i) typedef long long ll; const int N = 1e5 + 100; const int lim = 320; inline int read() { char c=getchar();int x=0,f=1; while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } using namespace std; int n, m, a[N]; int p[N], notp[N], nxt[N]; void init() { notp[1]=1; nxt[1]=1; rep(i,2,1e5) { if(!notp[i])p[++p[0]]=i,nxt[i]=i; rep(j,1,p[0]) { if(p[j]*i>1e5)break; notp[p[j]*i]=1; nxt[p[j]*i]=p[j]; if(i%p[j]==0)break; } } } int b[lim+3][N], v[N], cnt, c[N], sum[N], sumc[N]; void cal_pr(int x) { cnt=0; while(x!=1) { int t=nxt[x]; v[++cnt]=t; sum[t]=0; while(x%t==0)x/=t,++sum[t]; } } int belong[N], l[lim+3], r[lim+3], B, num, S[lim+3][N]; void build() { mem(sumc), mem(b), mem(S); B=sqrt(n); num=n/B;if(n%B)++num; rep(i,1,n)belong[i]=(i-1)/B+1; rep(i,1,num)l[i]=(i-1)*B+1,r[i]=i*B;r[num]=n; rep(i,1,n) { cal_pr(a[i]); rep(j,1,cnt) { if(v[j]<lim) b[v[j]][i]+=sum[v[j]]; else S[belong[i]][v[j]]+=sum[v[j]]; } c[i]=v[cnt];sumc[i]=sum[v[cnt]]; } rep(j,1,lim)rep(i,2,n) b[j][i]+=b[j][i-1]; } int fd(int L, int R, int x) { int tmp=0; if(R-L+1<=B) { rep(i,L,R) if(c[i]==x) tmp+=sumc[i]; return tmp>=sum[x]; } rep(i,L,r[belong[L]]) if(c[i]==x) tmp+=sumc[i]; rep(i,belong[L]+1,belong[R]-1) tmp+=S[i][x]; rep(i,l[belong[R]],R) if(c[i]==x) tmp+=sumc[i]; return tmp>=sum[x]; } int ck(int l, int r, int d) { int tmp=-1; cal_pr(d); rep(i,1,cnt) { if(v[i]<lim&&b[v[i]][r]-b[v[i]][l-1]<sum[v[i]]) return 0; if(v[i]>=lim) tmp=v[i]; } if(tmp==-1) return 1; return fd(l,r,tmp); } int main() { int T; init(); T=read(); while(T--) { n=read(), m=read(); rep(i,1,n) a[i]=read(); build(); rep(i,1,m) { int l,r,d; l=read(), r=read(), d=read(); if(ck(l,r,d)) puts("Yes"); else puts("No"); } } return 0; }