Codeforces 385C 线性筛素数

题意:给定一个数组,求[l,r] 区间,区间里的素数,数组中,能被这个素数整除的个数,再求和。

分析:区间很大,10^9了,找去区间内的素数是不可能的,但是,数组的数很小,而且要能整除区间内的素数,所以,这些很大的素数是没用的,筛出10^7以内的素数就ok了。

怎么算个数呢?

质因数分解,hash一下,再二分区间,应该是很麻烦了,但是网上还有麻烦的,还用到了线段树维护。

简单方式是:

将数组hash,在筛素数的时候,检测hash值,是否有这些数,有的话,记录到这个素数中,也就是说,这个数组中,能被这个素数整除的有s个,然后对s求一个前缀和,问题就转换为一个区间和。

#include <bits/stdc++.h>

using namespace std;

//10^7以内的素数
const int maxn = 10000000+5;

int vis[maxn],g[maxn],s[maxn];

int m;
int main(int argc, char const *argv[])
{
    memset(vis,0,sizeof(vis));
    memset(g,0,sizeof(g));
    memset(vis,0,sizeof(vis));
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++) {
        int x;
        scanf("%d",&x);
        g[x]++;
    }

    for(int i=2;i<maxn;i++) {
        if(vis[i]) continue;
        for(int j=i;j<maxn;j+=i) {
            if(g[j])
                s[i] +=g[j];
            vis[j] = 1;
        }
    }

    for(int i=1;i<maxn;i++)
        s[i] +=s[i-1];

    int a,b;
    scanf("%d",&m);
    for(int i=0;i<m;i++) {
        scanf("%d%d",&a,&b);
        if(a>=maxn) a = maxn-1;
        if(b>=maxn) b = maxn-1;
        printf("%d
",s[b]-s[a-1]);
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/TreeDream/p/7256779.html