UVa 11105 (筛法) Semi-prime H-numbers

题意:

你现在来到了一个所有的数都模4余1的世界,也就是除了这种数没有其他的数了。

然而素数的定义依然没变,如果一个数不能写成两个非1数字的乘积,则它是素数。

比如,在这里5就变成了最小的素数。

两个素数相乘得到一个半素数,比如5×5 = 25就是最小的半素数。

求1~h之间有多少个半素数。

分析:

虽然是要求[1, h]之间半素数的个数,但向往常筛普通素数一样先把所有的4k+1的素数筛出来。

然后二重循环枚举半素数,最后统计区间内[1, h]的半素数个数SUMh

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cmath>
 4 using namespace std;
 5 
 6 const int maxn = 1000000 + 1;
 7 bool vis[maxn + 10];
 8 int prime[100000], cnt, sum[maxn + 10];
 9 
10 void Init()
11 {
12     int m = sqrt(maxn + 0.5);
13     for(int i = 5; i <= m; i += 4) if(!vis[i])
14         for(int j = i * i; j <= maxn; j += i)
15             vis[j] = true;//H-素数筛选
16 
17     for(int i = 5; i <= maxn; i += 4) if(!vis[i]) prime[cnt++] = i;
18 
19     memset(vis, false, sizeof(vis));
20     for(int i = 0; i < cnt; i++)
21     {//筛选H-半素数
22         for(int j = i; j < cnt; j++)
23         {
24             long long k = (long long)prime[i] * (long long) prime[j];
25             if(k > (long long)maxn) break;
26             vis[k] = true;
27         }
28     }
29 
30     for(int i = 25; i <= maxn; i++) sum[i] = sum[i-1] + vis[i];
31 }
32 
33 int main()
34 {
35     freopen("in.txt", "r", stdin);
36     Init();
37     int n;
38     while(scanf("%d", &n) == 1 && n) printf("%d %d\n", n, sum[n]);
39 
40     return 0;
41 }
代码君

 

posted @ 2015-02-23 22:10  AOQNRMGYXLMV  阅读(331)  评论(0编辑  收藏  举报