Description
因为151即是一个质数又是一个回文数(从左到右和从右到左是看一样的),所以 151 号是回文质数。写一个程序来找出范围[a,b](5 <= a < b <= 100,000,000)间的所有回文质数;
Input
第 1 行: 二个整数 a 和 b
Output
输出一个回文质数的列表,一行一个。
Sample Input
5 500
Sample Output
5
7
11
101
131
151
181
191
313
353
373
383
问题:数值太大,先判断回文数,再判断素数,依然超时;
于是为了。。。为了缩短时间:
1、将除11以外的偶数位回文数剪掉。据说偶数位的回文数都可以被11整除,显然不是素数,结果出来只是减少了10ms左右,问题显然不是这个。
2、改善判断素数的算法,由2~sqrt(i)依次整除改为,判断
然后发现也只是减少了50ms左右,显然这不是主要问题。
3、将全部结果输出,发现最大素数为9989899<<100000000,所以加判断 if(b>=9989899) b=9989899;
结果通过了。
代码:
#include <iostream>
#include <stdio.h>
using namespace std;
int main()
{
int i,j,k,t;
int bool1,bool2;
int a,b;
int p1[15];
cin>>a>>b;
if(b>=9989899)
b=9989899;
for(i=a;i<=b;i++)
{
j=0;k=i;
while(k>0)
{
p1[j]=k%10;
j++;
k/=10;
}
if(j%2==0 && i!=11)
continue;
bool1=1;
for(t=0;t<j;t++)
{
if(p1[t]!=p1[j-1-t])
{
bool1=0;
break;
}
}
if(bool1==0)
continue;
bool2=1;
if(i%6!=1 && i%6!=5)
continue;
for(t=5;t*t<=i;t+=6)
{
if(i%t==0 || i%(t+2)==0)
{
bool2=0;
break;
}
}
if(bool2==0)
continue;
printf("%d",i);
printf("\n");
}
return 0;
}
7
11
101
131
151
181
191
313
353
373
383
问题:数值太大,先判断回文数,再判断素数,依然超时;
于是为了。。。为了缩短时间:
1、将除11以外的偶数位回文数剪掉。据说偶数位的回文数都可以被11整除,显然不是素数,结果出来只是减少了10ms左右,问题显然不是这个。
2、改善判断素数的算法,由2~sqrt(i)依次整除改为,判断
素数出现规律:
当n≧5时,如果n为素数,那么n mod 6 = 1 或 n mod 6 = 5,即n一定出现在6x(x≥1)
两侧。
证明:
当x
≥1时,有如下表示方法:
┈┈
6x,6x+1,6x+2,6x+3,6x+4,6x+5,6(x+1),6(x+1)+1┈┈
不在6x两侧的数为
6x+2
,
6x+3
,
6x+4,即2(3x+1),3(2x+1),2(3x+2),它们一定不是素数,所以素数一定出现在6x的两侧。
高效判断一个大于1的数是否为素数:
- bool isPrime(int num)
- {
- if (num == 2 || num == 3)
- {
- return true;
- }
- if (num % 6 != 1 && num % 6 != 5)
- {
- return false;
- }
- for (int i = 5; i*i <= num; i += 6)
- {
- if (num % i == 0 || num % (i+2) == 0)
- {
- return false;
- }
- }
- return true;
- }
然后发现也只是减少了50ms左右,显然这不是主要问题。
3、将全部结果输出,发现最大素数为9989899<<100000000,所以加判断 if(b>=9989899) b=9989899;
结果通过了。
代码:
#include <iostream>
#include <stdio.h>
using namespace std;
int main()
{
int i,j,k,t;
int bool1,bool2;
int a,b;
int p1[15];
cin>>a>>b;
if(b>=9989899)
b=9989899;
for(i=a;i<=b;i++)
{
j=0;k=i;
while(k>0)
{
p1[j]=k%10;
j++;
k/=10;
}
if(j%2==0 && i!=11)
continue;
bool1=1;
for(t=0;t<j;t++)
{
if(p1[t]!=p1[j-1-t])
{
bool1=0;
break;
}
}
if(bool1==0)
continue;
bool2=1;
if(i%6!=1 && i%6!=5)
continue;
for(t=5;t*t<=i;t+=6)
{
if(i%t==0 || i%(t+2)==0)
{
bool2=0;
break;
}
}
if(bool2==0)
continue;
printf("%d",i);
printf("\n");
}
return 0;
}