金山西山居初赛(2)第一题美素数--hdu4548

美素数满足两个条件:

1.该数本身是素数。

2.该数各位数字之和也是素数。

题目中的数据范围是1~1百万,如果使用暴力肯定tle。于是我就想到了打表,我把从1到1百万之间的所有美素数打出来。提交后发现,代码太长,没法提交^_^。所以就想到用一个数组在程序初始化的时候来记录满足条件的美素数。在1~1百万之间的美素数个数3万多些。再用二分法从3万个数据中找到下边界,然后循环出满足条件的个数输出。


#include<stdio.h>
int data[40000];//存放1到1百万之间的美素数

//判断一个数是否是素数
int isPrime(int n){
	int i;
	for(i=2;i*i<=n;i++){
		if(n%i==0)return 0;
	}
	return 1;
}

//将1到1百万之间美素数放到data数组中
void init(){
	int i,temp,sum;
	int num=0;
	for(i=2;i<1000000;i++){
		temp=i;
		sum=0;
		while(temp>0){
			sum=sum+temp%10;
			temp=temp/10;
		}
		//如果i的各位数之和是素数并且i也是素数。满足条件
		if(isPrime(sum) && isPrime(i)){
			data[num++]=i;
		}
	}
}
//二分查找,找到离a最近的那个下标.
int bSearch(int value){
	int left=0,right=30122;
	int index=(left+right)/2;
	while(left<=right){
		if(data[index]==value)return index;
		else if(data[index]>value){
			right=index-1;
		}else{
			left=index+1;
		}
		index=(right+left)/2;
	}
	return index;
}

int main(){
	int T,i,cnt=1,result;
	int a,b,pos;
	init();
	scanf("%d",&T);
	
	while(T--){
		result=0;
		scanf("%d%d",&a,&b);
		//将找到的下标值-2是为了确保下界的正确性。
		pos=bSearch(a)-2;
		if(pos<0)pos=0;
		for(i=pos;;i++){
			if(data[i]>=a && data[i]<=b)result++;
			if(data[i]>b)break;
		}
		printf("Case #%d:",cnt);
		cnt++;
		printf(" %d\n",result);
	}
	return 0;
}


你可能感兴趣的:(金山西山居初赛(2)第一题美素数--hdu4548)