POJ 3292 Semi-prime H-numbers——暴力和素数筛两种方法

Description

This problem is based on an exercise of David Hilbert, who pedagogically suggested that one study the theory of 4n+1 numbers. Here, we do only a bit of that.

An H-number is a positive number which is one more than a multiple of four: 1, 5, 9, 13, 17, 21,… are the H-numbers. For this problem we pretend that these are the only numbers. The H-numbers are closed under multiplication.

As with regular integers, we partition the H-numbers into units, H-primes, and H-composites. 1 is the only unit. An H-number h is H-prime if it is not the unit, and is the product of two H-numbers in only one way: 1 × h. The rest of the numbers are H-composite.

For examples, the first few H-composites are: 5 × 5 = 25, 5 × 9 = 45, 5 × 13 = 65, 9 × 9 = 81, 5 × 17 = 85.

Your task is to count the number of H-semi-primes. An H-semi-prime is an H-number which is the product of exactly two H-primes. The two H-primes may be equal or different. In the example above, all five numbers are H-semi-primes. 125 = 5 × 5 × 5 is not an H-semi-prime, because it’s the product of three H-primes.

Input

Each line of input contains an H-number ≤ 1,000,001. The last line of input contains 0 and this line should not be processed.

Output

For each inputted H-number h, print a line stating h and the number of H-semi-primes between 1 and h inclusive, separated by one space in the format shown in the sample.

Sample Input

21
85
789
0

Sample Output

21 0
85 5
789 62

题目解析:

这道题题目可能比较绕,首先讨论的数字必须都是4n+1,然后它分为units, H-primes, and H-composites,三个类型,第一个units就是1,第二个
H-primes是说h只能由1h得到,不能有其他组成方式,比如,9只能等于19,而没有其他(前面说了,这道题只考虑4n+1类数字),第三种就是说除以上两种的就都是H-composites。
然后,题目又给你一种H-semi-prime类型,这种类型是指只能由两个以上说的H-primes类型的数字的乘积得到,5 × 5 = 25, 5 × 9 = 45, 5 × 13 = 65, 9 × 9 = 81, 5 × 17 = 85.这些都是。但是125就不是,他没有办法做到两个H-primes相乘得到,125=255,但是25又不是H-primes,他还能拆成25=55.

题目解析:

  1. 超时方法有借鉴意义吧(毕竟是自己写的。。)
    这个程序确实可以输出正确答案,但就是很多过程没有必要,占了相当多的时间。
    思路就是先求出所有的4n+1,然后再接着得到所有的H-primes数,最后根据得到的H-primes数组,两两相乘可以得到H-semi-primes数。
    思路很简单、很暴力。。
    代码:
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<queue>
#include<vector>
#include<algorithm>
#include<utility>
#include<cmath>
#include<set>
#define inf 0x3f3f3f3f
using namespace std;

typedef long long ll;
typedef pair<int,int> P;

int Hnumbers[250010];
int Hprime[250000];


bool Judge(int x){
	int cnt=0;
	while(Hnumbers[cnt]<=sqrt(x)){
		if(x%Hnumbers[cnt]==0){
			return false;
		}
		cnt++;
	}
	return true;
}

void init(int &k1,int &k2,int &k3) {
	k1=0;
	k2=0;
	
	for(int i=5;i<=1000001;i=i+4){
		Hnumbers[k1++]=i;
	}

	for(int i=0;i<k1;i++){
		if(Judge(Hnumbers[i])){
			Hprime[k2++]=Hnumbers[i];
		}
	}
}
int solve(int x,int k2){
	
    set<int> myS;
	for(int i=0;i<k2;i++){
		//如果*5就大于x,后面的x就没有有必要考虑了
		if(Hprime[i]*5>x){
			break;
		}
		for(int j=i;j<k2;j++){
			if((ll)Hprime[i]*Hprime[j]<=x){
				myS.insert(Hprime[i]*Hprime[j]);
			}else{
				break;
			}
		}
	}
	return myS.size();
}

int main() {
	int x;
	//k1表示Hnumbers大小
//k2表示Hprime大小 
//k2表示Hsemi大小 
int k1,k2,k3;
	init(k1,k2,k3);
	while(scanf("%d",&x)!=EOF){
		if(x==0){
			break;
		} 
		printf("%d %d\n",x,solve(x,k2));
	}
	system("pause");
	return 0;
}

  1. AC代码
    利用了素数筛的思想做这道题
    原谅我一开始没有想到这一点
    思路也很简单清晰,就是一次考虑ij,然后如果i和j都是H-prime,那么就让ij=1,反之等于-1,最后再次重新遍历一次数组,得到最终结果
    注意:i和j为long long型,防止溢出(具体原因不太懂,有点奇怪,如果不用long long,慢慢地j就变成负数了)
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<queue>
#include<vector>
#include<algorithm>
#include<utility>
#include<cmath>
#define inf 0x3f3f3f3f
using namespace std;

typedef long long ll;
typedef pair<int,int> P;

int res[1000010];
void init(){
	memset(res,0,sizeof(res));
	for(ll i=5;i<250010;i+=4){
		for(ll j=i;j<250010;j+=4){
			if(i*j>1000001){
				break;
			}
			else if(res[i]==0&&res[j]==0){
				res[i*j]=1;
			}
			else{
				res[i*j]=-1;
			}
		}
	}
	int num=0;
	for(int i=5;i<=1000001;i+=4){
		if(res[i]==1){
			num++;
		}
		res[i]=num;
	}
}
int main() {
	int x;
	init();
	while(scanf("%d",&x)!=EOF){
		if(x==0){
			break;
		} 
		printf("%d %d\n",x,res[x]);
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值