POJ 3292 Semi-prime H-numbers 埃氏筛法

本文介绍了如何使用埃氏筛法计算HsimePrime,首先确定Hnumber,然后筛选出Hprime,接着找出HsimePrime并存储在数组中,最后通过输入查询HsimePrime的数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、思路

一个数字p,满足(p%4)==1,那么p就是Hnumber,我们先求出范围内的Hnumber,之后在范围内使用埃氏筛法打表,一开始认为除了0和1所有的数字都是Hpime,定义i从1开始循环到根号下1000001,如果i是(i%4)==1并且i是Hprime,把i所有的倍数都设置为Hprime。

之后找到范围内的所有Hprime,大约89000多个,之后1之后对于每个Humber如p,遍历根号p范围内的Hprime如q,如果其中p%q==0,并且p/q是Hprime,那么p就是HsimePrime,通过这个方法,可以找到所有的HsimePrime

定义一个数组arr,arr[i]存放i以内HsimePrime数量,如果i是simePrime,那么i等于HsimePrime[i-1]+1,否则HsimePrime[i-1],

之后对于每个值,直接从数组中找结果即可!

二、代码

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;
int Hnumber[250007], HnumberLen = 0;
int Hprime[250007], HprimeLen = 0;
int simePrime[1000007];
bool isPrime[1000007];
void calcHnumber()
{
    for (int i = 1; i <= 1000001; i += 4)
    {
        Hnumber[HnumberLen++] = i;
    }
}
void sieve()
{
    for (int i = 0; i <= 1000001; i++)
    {
        isPrime[i] = true;
    }
    isPrime[0] = false, isPrime[1] = false;
    for (int i = 1; i * i <= 1000001; i++)
    {
        if (!isPrime[i] || ((i % 4) != 1))
        {
            continue;
        }
        for (int j = i * 2; j <= 1000001; j += i)
        {
            isPrime[j] = false;
        }
    }
}
void calcHprime()
{
    for (int i = 0; i <= 1000001; i++)
    {
        if (isPrime[i] && ((i % 4) == 1))
        {
            Hprime[HprimeLen++] = i;
        }
    }
}
void calcHsemiPrime()
{
    simePrime[0] = 0;
    simePrime[1] = 0;
    ll calcCount = 0;
    for (int i = 1; i < HnumberLen; i++)
    {
        int hNumber = Hnumber[i];
        bool flag = false;
        for (int j = 0; j < HprimeLen; j++)
        {
            int hPrimeNum = Hprime[j];
            ll hPrimeFang = hPrimeNum;
            hPrimeFang *= hPrimeFang;
            if (hPrimeFang > hNumber)
            {
                break;
            }
            if (hNumber % hPrimeNum == 0 && (isPrime[(hNumber / hPrimeNum)]))
            {
                flag = true;
                break;
            }
        }
        if (flag)
        {
            simePrime[hNumber] = simePrime[Hnumber[i - 1]] + 1;
        }
        else
        {
            simePrime[hNumber] = simePrime[Hnumber[i - 1]];
        }
    }
}
int main()
{
    sieve();
    calcHnumber();
    calcHprime();
    calcHsemiPrime();
    int p = 0;
    while (true)
    {
        scanf("%d", &p);
        if (p == 0)
        {
            break;
        }
        printf("%d %d\n", p, simePrime[p]);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值