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.
题目解析:
超时方法有借鉴意义吧(毕竟是自己写的。。)
这个程序确实可以输出正确答案,但就是很多过程没有必要,占了相当多的时间。
思路就是先求出所有的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;
}
- 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;
}