题意:定义了一种H素数,H素数的定义是能够被4整除余数为1,且不能写成两个不是1的H数的乘积,然后给定一个n值,问1到n中有多少个能被分解成两个H素数的数。
已经规定1不是h素数了,h数是满足4*n+1的数,所以先预处理出h数,再用筛法将一个h素数的倍数标记掉,同时生成h素数表,之后,枚举两个h素数的乘积,加一个判断大于100001时 break,也就是范围的上限,所以很快,最后递推一下0到i之间存在的h半素数的个数。
#include <iostream>
#include <cstdio>
#include <bitset>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <cmath>
#include <set>
#include <queue>
using namespace std;
typedef long long ll;
const int INF=1e9+100;
const int mod=1e9+7;
const int maxn=1000005;
int t=0;
int b[maxn],d[maxn];
int a[maxn],h[maxn];
void init(){
for(int i=0;4*i+1<=1000001;i++)
a[4*i+1]=1;
int cnt=0;
for(int i=5;i<=1001001;i++){
if(a[i]==1){
h[cnt++]=i;
for(int j=i*2;j<=1000001;j+=i){
a[j]=0;
}
}
}
for(int i=0;i<cnt;i++)
for(int j=i;j<cnt;j++){
if(1LL*h[i]*h[j]>1000001) break;
b[h[i]*h[j]]=1;
}
for(int i=1;i<=1000001;i++){
d[i]=d[i-1];
if(b[i]==1) d[i]++;
}
}
int main(){
//freopen("out.txt","w",stdout);
int n;
init();
while(scanf("%d",&n)&&n){
printf("%d %d\n",n,d[n]);
}
return 0;
}