您的位置:首页 > 其它

USACO 1.5.2 Prime Palindromes 回文质数

2013-07-25 10:39 295 查看

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)依次整除改为,判断
素数出现规律:
当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的数是否为素数:

[cpp]
view plaincopyprint?

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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: