题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4548
解题报告:一开始本想先打个素数表,然后每次输入L 跟R 的时候都进行暴力判断,但这题测试数据太多,有1W ,这样就达到10^10级别了,很明显不能过,但是,我后来一想,数状数组不就是用来解决区间问题的吗,顿时焕然大吾。我的做法就是先打个1到1000000的素数表,然后暴力判断从1到1000000每个数是不是美素数,同时把结果存到数状数组里面去。这样就可以实现存完了就可以实现快速查找了。
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<cmath> 5 6 const int maxn = 1000000; 7 8 int prim[maxn+5],tree[maxn+5]; 9 10 void dabiao() 11 { 12 memset(prim,0,sizeof(prim)); 13 prim[1] = 1; 14 for(int i = 4;i <= maxn;i += 2) 15 prim[i] = 1; 16 int M = sqrt(maxn); 17 for(int i = 2;i <= M;++i) 18 if(prim[i] == 0) 19 for(int j = i*i;j<=maxn;j+=i) 20 prim[j] = 1; 21 } 22 23 24 int judge(int n) 25 { 26 int sum = 0; 27 while(n) 28 { 29 sum += n%10; 30 n /= 10; 31 } 32 return sum; 33 } 34 35 void add(int n) 36 { 37 if(n > maxn) 38 return ; 39 for(int i = n;i <= maxn;i += (i&-i)) 40 tree[i]++; 41 } 42 void dabiao2() 43 { 44 memset(tree,0,sizeof(tree)); 45 for(int i = 1;i <= maxn;++i) 46 if(!prim[i] && !prim[judge(i)]) 47 add(i); 48 } 49 50 int sum(int L,int R) 51 { 52 int tot1 = 0,tot2 = 0; 53 for(int i = L-1;i >= 1; i -= (i&-i)) 54 tot1 += tree[i]; 55 for(int i = R;i >= 1;i -= (i&-i)) 56 tot2 += tree[i]; 57 return tot2 - tot1; 58 } 59 60 int main() 61 { 62 dabiao(); 63 dabiao2(); 64 int T,L,R,l = 1; 65 scanf("%d",&T); 66 while(T--) 67 { 68 scanf("%d %d",&L,&R); 69 printf("Case #%d: %d ",l++,sum(L,R)); 70 } 71 return 0; 72 }