1. 程式人生 > >POJ3292 UVA11105 Semi-prime H-numbers【篩法打表】

POJ3292 UVA11105 Semi-prime H-numbers【篩法打表】

問題簡述:參見上述連結。

問題分析

H-number:4n+1的數,n>=0,例如1,5,9,13,17,21,......

H-prime:H-number數並且其因子只有1和它本身。

H-semi-prime:兩個H-prime的乘積。

H-composite:其他H-number數。

需要注意的一點是,兩個H-number的乘積=(4n+1)*(4m+1)=4*4m*n+4n+4m+1是一個H-number數。

這個問題是對於輸入的h,求1-h之間H-semi-prime數的數量。

根據篩選法的原理進行篩選,先篩選出H-semi-prime,再做一下統計計算。

程式說明

陣列h_number[],若h_number[i]=0表示i為H-prime,h_number[i]=1表示i為H-semi-primes,h_number[i]=-1表示i為H-composite。

統計處理後,h_number[i]=k表示1-i中有k個H-semi-primes

AC的C++語言程式如下

/* POJ3292 UVA11105 Semi-prime H-numbers */

#include <iostream>
#include <cstring>

using namespace std;

const int MAX_H_NUMBER = 1000001;
int h_number[MAX_H_NUMBER + 1];     //h_number[i]=0表示i為H-prime

void maketable(int n)
{
    memset(h_number, 0, sizeof(h_number));

    for(int i=5; i<=n; i+=4)
        for(int j=5; j<=n; j+=4) {
            int product = i * j;
            if(product > n)
                break;

            if(h_number[i] == 0 && h_number[j] == 0)
                h_number[product] = 1;      // product為H-semi-primes
            else
                h_number[product] = -1;     // product為H-composite
        }

    // 統計H-prime
    int hpcount = 0;
    for(int i=1; i<=n; i++) {
        if(h_number[i] == 1)
            hpcount++;
        h_number[i] = hpcount;  // 1-i有hpcount個H-prime
    }
}

int main()
{
    int h;

    maketable(MAX_H_NUMBER);

    while(cin >> h && h)
        cout << h << " " << h_number[h] << endl;

    return 0;
}