例1.2-2 Semi-prime H-numbers

问题描述:

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;
}

猜你喜欢

转载自blog.csdn.net/sdau20171989/article/details/81265465