题意:
给你一个区间,问你这个区间中的数既是素数又是美素数的数有多少个?美素数:首先这个数本身必须是素数并且它的各位数字的和也是素数; 如29,本身是素数, 而且2+9 = 11也是素数, 所以它是美素数.
分析:
要筛选素数直接用埃拉托塞尼筛素数法, 然后枚举从n~m(n为1时从2开始)中的美素数, 是不是特简单觉得肯定能AC; 不过提交显示TLE, 为什么呢?因Tmax =1000, mmax = 1000000, 这样筛一下就已经超时了, 更不说再去枚举了; 那可以这样在输入数据之前就将1e6之内的素数筛出来, 再枚举n~m,然而还是不行,1e6有将80000个素数照样TLE;对于输入数据量比较大而结果很小时, 可以采用计数排序.
代码如下:
1 #include <iostream>
2 #include <cstdio>
3 #include <cstring>
4 #include <fstream>
5 #include <ctime>
6 #include <cmath>
7 #include <cstdlib>
8 #include <algorithm>
9 #include <set>
10 #include <map>
11 #include <list>
12 #include <stack>
13 #include <queue>
14 #include <iterator>
15 #include <vector>
16
17 using namespace std;
18
19 #define LL long long
20 #define INF 0x3f3f3f3f
21 #define MOD 1000000007
22 #define MAXN 10000010
23 #define MAXM 1000010
24
25 const int maxn = 1000005;
26 int vis[maxn], prime[maxn];
27
28 void sieve(int n)
29 {
30 int m = sqrt(n+0.5);
31 memset(vis, 0, sizeof(vis));
32 memset(prime, 0, sizeof(prime));
33 for(int i = 2; i <= m; i++ )
34 if(!vis[i])
35 for(int j = i*i; j <= n; j += i ) //每次增加i
36 vis[j] = 1;
37 }
38
39 int count_sum(int n)
40 {
41 int sum = 0;
42 while(n > 0)
43 {
44 sum += n%10;
45 n /= 10;
46 }
47 return sum;
48 }
49
50 void gen_prime(int n)
51 {
52 sieve(n);
53 for(int i = 2; i <= n; i++ )
54 {
55 if(!vis[i]&&!vis[count_sum(i)])
56 prime[i] = prime[i-1] + 1;
57 else
58 prime[i] = prime[i-1];
59 }
60 }
61
62 int main()
63 {
64 gen_prime(maxn);
65 int t;
66 int kase = 0;
67 scanf("%d", &t);
68 while(t--)
69 {
70 int n, m;
71 scanf("%d%d", &n, &m);
72 printf("Case #%d: %d
", ++kase, prime[m]-prime[n-1]); //表示区间[n,m]的美素数个数,区间的长度为m-(n-1).
73 }
74
75 return 0;
76 }