题解 UVA11105 【H-半素数 Semi-prime H-numbers】
POJ3292/UVA11105 H-半素数 Semi-prime H-numbers
Luogu RemoteJudge
POJ-Vjudge
UVA-Vjugde
Blog阅读效果更佳
题意
给你一个由
题解
在数学一本通里面看到的这题,觉得那个写的太差了啥都没看懂,决定写一发题解。(就是自己太菜了
首先可以想到最朴素的做法就是直接预处理一个
据说这样是可以过的,但是我也不知道。
可以优化的地方就在找质数这个地方。考虑埃氏筛的过程,我们可以把每次枚举的数改一改,从i++ 变为i+=4,这样我们每次就枚举的都是
据说这样也是可以过的,但是我还是不知道。
引理:若
证明:设
由原式可得:
观察后面
显然:
将
又因为
证毕。
所以可以再次修改埃氏筛除合数的过程,将范围修改为:j++修改为j+=i*4
Code
#include <iostream>
#include <cstdio>
using namespace std;
const int SIZE = 1e6 + 5;
int h, cnt;
int h_prime[SIZE], h_semi[SIZE], vis[SIZE], sum[SIZE];
inline int read()
{
char ch = getchar();
int f = 1, x = 0;
while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + ch - '0'; ch = getchar(); }
return x * f;
}
inline void init()
{
for (int i = 5; i <= SIZE - 5; i += 4) {
if (vis[i]) continue;
h_prime[++cnt] = i;
for (int j = i * 5; j < SIZE; j += i * 4) vis[j] = 1;
}
for (int i = 1; i <= cnt; i++)
for (int j = 1; j <= i && h_prime[i] * h_prime[j] < SIZE; j++) h_semi[h_prime[i] * h_prime[j]] = 1;
for (int i = 1; i < SIZE; i++) sum[i] = sum[i - 1] + h_semi[i];
}
int main()
{
init();
h = read();
while (h) {
printf("%d %d\n", h, sum[h]);
h = read();
}
return 0;
}
写了介么详细不妨给个赞?