题意:
有一种数叫H-number,什么是H-number,就是等于4*n+1的数,所有的H-number mod 4 等于 1。
H-number分为H-prime和H-composite两类,H-prime是不能被自己和1以外的其他H-number整除的数。剩下的就都是H-composite数了。
注意,9是H-prime,
虽然9在自然数中能被3整除,但是在H-number中,它只能分解成1*9,因为3不是
H-number。
现在,题目又给出一种数,叫H-semi-prime,首先它是一个H-number,即满足 mod 4等于1。
其次,它是恰好两个H-primes的乘积。
如25 = 5*5,125 = 5*5*5,所以25是H-semi-prime,而125不是。
如今题目给一个任意的属于H-number的数h,h<=1000001,求从1到h的H-number中,属于H-semi-primes的数的个数。
1.变型艾氏筛法打表,找出所有H-prime。
如果i是H-prime,那么5*i+4*i*x(x>=0)一定不是H-prime。
ps:这是看的别人的解知道的。。。
出处:http://www.hankcs.com/program/cpp/poj-3292-semi-prime-h-numbers.html
2.得到满足题目范围的H-prime的两两乘积。
mul = h-prime[i]*h-prime[j]
3.H-semi-primes[mul] 表示从1到mul中所有的h-semi-prime的个数
写个循环搞定
注意数据大小,注意数据大小,注意数据大小(mul)
下面是代码:
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef unsigned long long ULL;
const int maxn = 1000005;
int h_prime[maxn];
bool is_h_prime[maxn];
int h_semi_prime[maxn];
int p;
//打表变型,如果i是h-prime,那么5*i+4*i*x不是h-prime。
void sieve() {
memset(is_h_prime,false,sizeof(is_h_prime));
for(int i=5; i<=maxn; i+=4) is_h_prime[i] = true;
for(int i=5; i<=maxn; i+=4) {
if(is_h_prime[i]) {
h_prime[p++] = i;
for(int j=5*i; j<=maxn; j+=4*i) is_h_prime[j] = false;
}
}
}
void get_semi_prime_h() {
memset(h_semi_prime,0,sizeof(h_semi_prime));
for(int i=0; i<p; i++) {
for(int j=0; j<=i; j++) {
if(h_prime[j]>10000) break;
ULL mul = h_prime[i]*h_prime[j];
if(mul>maxn) break;
h_semi_prime[mul] = 1;
}
}
for(int i=1; i<=maxn; i++) {
h_semi_prime[i]+=h_semi_prime[i-1];
}
}
int main() {
int h;
p = 0;
sieve();
get_semi_prime_h();
while(cin>>h&&h!=0) {
cout<<h<<' '<<h_semi_prime[h]<<endl;
}
}
这里给出类似的稍有不同的解法,可以对比多加思考
http://www.cnblogs.com/program-ccc/p/5682470.html