POJ - 3292 Semi-prime H-numbers(素数筛选)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/a54665sdgf/article/details/81195305

题目大意:在所有的H-数(形如4n+1的数)中,找出一定范围内的由两个H-素数(H公因数只有1和它本身)相乘得到的数(Semi-prime)。

思路:

这道题我一开始做得很麻烦,仿照普通的素数筛选方法,把所有的H素数筛选出来之后,再把所有的H数一个一个判断是否为Semi-prime,不过还是勉强AC了。

之后我又将代码改写了一遍。为了便于理解,我进行了两次筛选,第一次筛选出所有的H素数,第二次筛选出所有的Semi-prime,然后按照前缀和的思想把所有范围内的Semi-prime累加起来,就ok了。

筛选的过程中,我省去了许多判断条件,其实对运行速度几乎没什么影响。

ps:在1-n中找出所有的满足i*j<=n的组合,其时间复杂度为O(nlogn)而不是O(n^2)。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<algorithm>
#include<map>
#define FRER() freopen("i.txt","r",stdin)

using namespace std;
typedef long long ll;
const int N=1000000+100;
int Type[N],n;
int d[N];

void PrimeProduce()
{
    memset(Type,0,sizeof Type);
    for(int i=5; i<N; i+=4)
        for(int j=5; i*j<N; j+=4)
            Type[i*j]=1;
}

void SemiPrimeProduce()
{
    for(int i=5; i<N; i+=4)
        for(int j=5; i*j<N; j+=4)
            if(Type[i]==0&&Type[j]==0)
                Type[i*j]=2;
}

int main()
{
    //FRER();
    PrimeProduce();
    SemiPrimeProduce();
    for(int i=5; i<N; ++i)
    {
        d[i]+=d[i-1];
        if(Type[i]==2)d[i]++;
    }
    while(scanf("%d",&n)&&n)
    {
        printf("%d %d\n",n,d[n]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/a54665sdgf/article/details/81195305