hdu 6287 快速质因数分解,统计思想

http://acm.hdu.edu.cn/showproblem.php?pid=6287

记录每一个质数存在的下标,比如数据
2 4 8 16
那么v[2]={1,2,2,3,3,3,4,4,4,4};
表示2这个质数在数据中出现的下标。用vector可以实现。查询之前先处理好每个质数的数组
那么查询[l,r]=[2,4]中, 有2的多少次方:
upper_bound(v[2].begin(),v[2].end(),r)-lower_bound(v[2].begin(),v[2].end(),l)
答案是9,表示l到r之间最多能够组成2的9次方;

对查询中的数d进行质因数分解,再逐个质因数进行查询即可解决。
对某个数进行质因数分解时,分解过程中若a为质数,则跳出循环,不然会卡时间
typedef long long ll;
typedef pair<int,int> P;
int n,m,a,l,r,d;
vector<int>v[100005];
int p[100005],np[100005],pcnt;
void primediv(int n){
    memset(np,0,sizeof np);pcnt=0;
    for(int i=2;i<=n;i++){
        if(np[i]==0){
            p[pcnt++]=i;
        }
        for(int j=0;j<pcnt && p[j]*i<=n;j++){
            np[p[j]*i]=1;
            if(i%p[j]==0)break;
        }
    }
}
void resolve(int a, int k){
    for(int i=0;np[a];i++){
        while(a%p[i]==0){
            v[p[i]].push_back(k);
            a/=p[i];
        }
    }
    if(a>1)v[a].push_back(k);//important!
}
int main(){
    primediv(100001);
    int t;
    scanf("%d",&t);
    while(t--){
        for(int i=0;i<pcnt;i++)v[p[i]].clear();
        scanf("%d %d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%d",&a);
            resolve(a,i);
        }
        while(m--){
            scanf("%d %d %d",&l,&r,&d);
            int flag=1;
            for(int i=0, num=0;np[d] && flag;i++){
                while(d%p[i]==0)
                    d/=p[i],num++;
                if(num){
                    int cnt=upper_bound(v[p[i]].begin(),v[p[i]].end(),r)
                            -lower_bound(v[p[i]].begin(),v[p[i]].end(),l);
                    if(cnt<num)flag=0;
                    num=0;
                }
            }
            if(flag && d>1){//important
                int cnt=upper_bound(v[d].begin(),v[d].end(),r)
                        -lower_bound(v[d].begin(),v[d].end(),l);
                if(cnt<1)flag=0;
            }
            if(flag)printf("Yes\n");
            else printf("No\n");
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/kang000/p/9169156.html