一、思路
一个数字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;
}