Peter's codebook A blog full of codes

POJ 3292 Semi-prime H-numbers

Semi-prime H-numbers

傳送門

POJ3292

題目概述

一個數字是 H-number 的定義是,它是正整數且可以寫成 4n+1 (n為大於等於 0 的整數) 的形式。 H-number 只有三種, unit、H-prime、H-composite, 1 是唯一的 unit , H-prime 的定義是,若一個 H-number 不是 unit 且只能被分解為以下形式 ,否則,這個數字即為 H-composite。

還有一個定義叫做 H-semi-prime ,就是一個 H-number 可以被洽兩個 H-prime 相乘組成。

現在,給一個 H-number H ,問介於 [1, H] 有多少個 H-semi-prime ?

解題想法

使用篩法,先建出題目範圍內的 H-prime 表,之後就可以快速判斷 H-number 是否為 H-prime。 要判斷 H-semi-prime ,首先要判斷該 H-number 不是 H-prime ,且該 H-number 整除某個 H-prime 的商必須也是 H-prime ,這樣可以得到 H-semi-prime 的表,之後再用這個表做 Prefix sum ,就可以快速求出區間內的 H-semi-prime 數量。

程式碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <iostream>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <functional>
#include <algorithm>
using namespace std;
const size_t MAXN=50000;
bool is_p[MAXN];
vector<int>plist;

void mk_p() {
    fill(is_p,is_p+MAXN,false);
    for(int i=5; i<MAXN; i+=4) is_p[i]=true;
    for(int i=5; i<MAXN; i+=4) {
        if(is_p[i]) {
            plist.push_back(i);
            for(int j=i+i; j<MAXN; j+=i) is_p[j]=false;
        }
    }
}

inline bool is_prime(int n) {
    if(n<MAXN) return is_p[n];
    for(vector<int>::iterator v=plist.begin(); v!=plist.end() && (*v)*(*v)<=n; ++v) {
        if(n%(*v)==0)return false;
    }
    return true;
}
inline bool is_hprime(int n) {
    if(n<MAXN && is_p[n]) return false;
    for(vector<int>::iterator v=plist.begin(); v!=plist.end() && (*v)*(*v)<=n; ++v) {
        if(n%(*v)==0 && is_prime(n/(*v)))return true;
    }
    return false;
}

vector<int>is_hp;

void build() {
    is_hp.clear();
    is_hp.push_back(0);
    for(int i=1; i<=1000002; i+=4) is_hp.push_back( is_hprime(i)?1:0 );
    for(vector<int>::iterator v=is_hp.begin()+1; v!=is_hp.end(); ++v) {
        *v = *v + *(v-1);
    }
}
int get_psum(int i, int j) {
    return is_hp.at(j) - is_hp.at(i-1);
}

int solv(int n) {
    return get_psum(1, ((n-1)/4)+1);
}  

int main(void) {
    int n;
    mk_p();
    build();
    while(scanf("%d",&n)!=EOF && n) {
        printf("%d %d\n",n , solv(n));
    }
    return 0;
}
comments powered by Disqus