问题描述:
H-数指形如4n+1的数,乘法在H数的集合内是封闭的。
在这个集合内:
只能被1和本身整除的数叫做H-素数(不包括1),其余的数叫做H-合数。
能且只能分解成两个H-素数的H-合数,叫做H-合成数。
求0到h范围内的H-合成数。
要求:输入若干行,每行一个小于1000001的整数h,一个0表示结束。输出一个数表示答案。
分析:
如果i是H-素数,则5i+4i*x一定是H数,但不是H-素数。
步骤:
step1:利用分析所得规律,求出所有H-素数,利用H_prime[]标记;
step2:枚举所有H-合成数,用is_H_semiprime[]标记;
step3:事先求出各个h段的H-合成数的数目,用accumulate[]存储;
step4:输入h后直接输出。
代码:
#include<iostream>
using namespace std;
#define MAX_h 1000001+16
bool is_H_noprime[MAX_h];//标记H-合数
int H_prime[MAX_h];//存储H-素数
bool is_compositenum[MAX_h];//标记H-合成数
int accumulate_[MAX_h];
int n;
int main()
{
for(int i=5;i<MAX_h;i+=4)
{
if(is_H_noprime[i])continue;
H_prime[++n]=i;//存储H-素数
for(int j=5*i;j<MAX_h;j+=4*i)
{
is_H_noprime[j]=true;//标记H-合数
}
}
for(int i=1;i<=n;i++)
for(int j=1;j<=i&&H_prime[j]*H_prime[i]<MAX_h;j++)
{
is_compositenum[H_prime[i]*H_prime[j]]=true;//标记H-合成数
}
for(int i=1;i<MAX_h;++i)
{
accumulate_[i]=accumulate_[i-1]+is_compositenum[i];//直接存储好相应范围内的个数
}
int h;
cin>>h;
while(h)
{
cout<<accumulate_[h]<<endl;
cin>>h;
}
return 0;
}