一道很棒的数学题。
思路:先筛出“素数”,然后将“素数”两两相乘,枚举出范围以内的“合成数”,再计算前缀和。最后直接输出。
#include<iostream> #include<cstring> #include<cmath> #define INF 1000001 using namespace std; bool ip[250001],hp[250001];//ip记录“素数”,hp记录“合成数” int s[250001];//前缀和 int main() { int R=sqrt(INF); for(int i=5;i<=R;i+=4){//“素数”筛法 if(!ip[i/4]){ for(int j=5;i*j<=INF;j+=4) ip[i*j/4]=1; } } for(int i=5;i<=R;i+=4){//两两相乘,枚举“合成数” for(int j=i;i*j<=INF;j+=4){ if(!ip[i/4]&&!ip[j/4]) hp[i*j/4]=1; } } for(int i=1;i<=INF/4;i++){//计算前缀和(前i个H数中的“合成数”个数) s[i]=s[i-1]; if(hp[i]) s[i]++; } while(1){ int h; cin>>h; if(h==0) return 0; cout<<s[h/4]<<endl;//直接输出 } }