BZOJ 5358 口算训练/HDU 6287(可持久化线段树)

题意:给你L,R区间然后给你一个K,询问L到R区间的数知否能整除K

思路:因为我们是判断是否整除,所以我们可以对每一个数进行质因数分解,然后判断L到R区间内的数质因数分解后的个数大小就可以了,然后就是打表,进行主席树维护

代码:

#include <cstdio>

const int maxn=1e5+7;
bool prime[maxn];
int pri[maxn],id[maxn],tot=0;
int root[maxn];
struct node
{
    int l,r,sum;
}T[maxn*40];
int cnt;
inline int read()
{
    int x=0;char ch=getchar();
    while (ch<'0'||ch>'9') ch=getchar();
    while (ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
    return x;
}

void getprime()
{
    for(int i=2;i<maxn;i++){
        if(!prime[i])pri[++tot]=i,id[i]=tot;
        for(int j=1;j<=tot&&pri[j]*i<maxn;j++){
            prime[pri[j]*i]=1;
            if(i%pri[j]==0)break;
        }
    }
}

void update(int l,int r,int &x,int pos,int v)
{
    T[++cnt]=T[x],x=cnt;
    if(l==r){
        T[x].sum+=v;
        return ;
    }
    int mid=(l+r)>>1;
    if(pos<=mid)update(l,mid,T[x].l,pos,v);
    else update(mid+1,r,T[x].r,pos,v);
}

bool query(int l,int r,int x,int y,int pos,int v)
{
    if(l==r){
        return T[y].sum-T[x].sum>=v;
    }
    int mid=(l+r)>>1;
    if(pos<=mid)query(l,mid,T[x].l,T[y].l,pos,v);
    else query(mid+1,r,T[x].r,T[y].r,pos,v);
}
int main()
{
    getprime();
    int t,n,m,x,l,r,k,num,ok;
    scanf("%d",&t);
    while(t--){
        cnt=0,n=read();m=read();
        for(int i=1;i<=n;i++){
            root[i]=root[i-1];
            x=read();
            for(int j=1;j<=tot&&pri[j]*pri[j]<=x;++j){
                num=0;
                while(x%pri[j]==0)x/=pri[j],++num;
                if(num)update(1,tot,root[i],j,num);
            }
            if(x!=1)update(1,tot,root[i],id[x],1);
        }
        for(int i=1;i<=m;i++){
            l=read(),r=read(),k=read();
            ok=false;
            for(int j=1;j<tot&&pri[j]*pri[j]<=k;j++){
                num=0;
                while(k%pri[j]==0)k/=pri[j],++num;
                if(num&&!query(1,tot,root[l-1],root[r],j,num))ok=1;
                if(ok)break;
            }
            if(k!=1&&!query(1,tot,root[l-1],root[r],id[k],1))ok=1;
            if(ok)puts("No");
            else puts("Yes");
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/lalalatianlalu/p/9174838.html