做这道题之前首先要掌握的是线性筛的模板
附上题目链接
https://www.luogu.org/problem/P3383
首先这道题目的范围有些特殊必须是% 4 == 1的数才行
所以可以这样
直接把线性筛的模板拿过来将里面的每个数挨个枚举,每一次的++i 或者++j可以改为 += 4
这样每一次枚举的就都是“H数 ”了
然后不考虑“H数 ”之外的数,用这里面的数进行素数筛选 将H-素数都筛出来
在最后的时候两重循环枚举素数将他们的乘积标注出来最后 剩下的H数就都会是H-合数了
完整代码
#include<iostream> #include<cstdio> #include<cmath> using namespace std; const int Max = 1000005; const int M = 1000001; int ans[Max]; bool use[Max]; bool vis[Max]; int prime[Max]; int a[Max]; int js = 0; int main() { int tot = 0; for(int i = 5;i <= M;i += 4) { if(use[i] == true)continue; prime[++ tot] = i; for(int j = 1;j * i <= M;j += 4)//线性筛模板晒出H-素数 use[i * j] = true; } for(int i = 1;i <= tot;i ++) { for(int j = 1;j <= tot;j ++)//双重循环枚举 { if(prime[i] * prime[j] > M)break;//大于最大的范围break掉这一层循环 vis[prime[i] * prime[j]] = 1;//标记出来 } } for(int i = 1;i <= M;++ i) { ans[i] += ans[i - 1];//先继承前面H-合数的个数 if(vis[i] == true)//如果当前的数也是H-合数 ans[i] ++;//计数器累加 } int n; while(scanf("%d",&n)) { if(n == 0)break; else cout<<n<<" "<<ans[n]<<endl; } return 0; }