美素数
Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 8850 Accepted Submission(s): 3027
Problem Description
小明对数的研究比较热爱,一谈到数,脑子里就涌现出好多数的问题,今天,小明想考考你对素数的认识。
问题是这样的:一个十进制数,如果是素数,而且它的各位数字和也是素数,则称之为“美素数”,如29,本身是素数,而且2+9 = 11也是素数,所以它是美素数。
给定一个区间,你能计算出这个区间内有多少个美素数吗?
问题是这样的:一个十进制数,如果是素数,而且它的各位数字和也是素数,则称之为“美素数”,如29,本身是素数,而且2+9 = 11也是素数,所以它是美素数。
给定一个区间,你能计算出这个区间内有多少个美素数吗?
Input
第一行输入一个正整数T,表示总共有T组数据(T <= 10000)。
接下来共T行,每行输入两个整数L,R(1<= L <= R <= 1000000),表示区间的左值和右值。
接下来共T行,每行输入两个整数L,R(1<= L <= R <= 1000000),表示区间的左值和右值。
Output
对于每组数据,先输出Case数,然后输出区间内美素数的个数(包括端点值L,R)。
每组数据占一行,具体输出格式参见样例。
每组数据占一行,具体输出格式参见样例。
Sample Input
3 1 100 2 2 3 19
Sample Output
Case #1: 14 Case #2: 1 Case #3: 4
代码:
#include <stdio.h>
#include <math.h>
int m[1000002];
int sushu(int a)//判断是不是素数
{
int i,end=sqrt(a);
for(i=2;i<=end;i++)
{
if(a%i==0)
return 0;
}
return 1;
}
int qiuhe(int a)//求和
{
int sum=0;
while(a)
{
sum=sum+a%10;
a=a/10;
}
return sum;
}
void dabiao()//打表
{
int s=1,i;
m[1]=0;
m[2]=1;
for(i=3;i<=1000000;i=i+2)
{
if(sushu(i)&&sushu(qiuhe(i)))
s++;
m[i]=s;
m[i+1]=s;
}
}
int main()
{
int n,a,b,i=0;;
dabiao();
scanf("%d",&n);
while(n--)
{
i++;
scanf("%d%d",&a,&b);
printf("Case #%d: %d\n",i,m[b]-m[a-1]);
}
return 0;
}
一道水题做了两个小时,水平是真的挺差。。。
一开始每次都判断,果然时间超限。。。
数据太大1~1000000,应该用打表法
打表法粗略介绍:如一个测试用例让你求从2开始第1000位的素数是多少,那么你可以将前1000个已经列出来的存起来,如果下一题目再问到小于1000的情况,前面已经计算过了,那么我们就可以直接输出。所以第二个测试用例让你求第500位素数,那么我们直接将存起来的结果输出就可以了,如果第三个测试用例让我们求第3500个,那么我们就从第1001个算起,算出的结果继续存起来,以备下一次的实用,如此类推,这个存起来的过程就叫做打表。
注意:
1.
下面的有关打表的这一套中的数组m,好像只能在头文件下面声明,而且注意定义到1000002,因为打表的这个函数里的for循环里有m[i]=s;紧接着就是m[i+2]=s,当i=999999时,+2就等于1000001,所以要定义到1000002
还有一个地方需要注意,就是 FOR循环条件里的i=i+2,因为偶数除了2是素数,其余都不是素数(有因子2)
int m[1000002];
void dabiao()//打表
{
int s=1,i;
m[1]=0;
m[2]=1;
for(i=3;i<=1000000;i=i+2)
{
if(sushu(i)&&sushu(qiuhe(i)))
s++;
m[i]=s;
m[i+1]=s;
}
}
int main()
dabiao();
2.非常重要的一点,否则会时间超限那就是判断素数志勇判断到i<=sqrt(a)!!!!!!!!!!!
3.a<= <=b之间素数的个数是m[b]-m[a-1]