poj 3292 艾氏筛法的变型

本文介绍了一种特殊的数——H-semi-prime数,这类数为两个H-prime数的乘积,并且自身也是H-number。文章通过变型艾氏筛法找到所有H-prime数,并进一步计算出H-semi-prime数的数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:

有一种数叫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

生气

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值