USACO Section 1.5 Prime Palindromes

来源:互联网 发布:水利设计软件 编辑:程序博客网 时间:2024/05/17 06:02

题目原文

Prime Palindromes

The number 151 is a prime palindrome because it is both a prime number and a palindrome (it is the same number when read forward as backward). Write a program that finds all prime palindromes in the range of two supplied numbers a and b (5 <= a < b <= 100,000,000); both a and b are considered to be within the range .

PROGRAM NAME: pprime

INPUT FORMAT

Line 1:Two integers, a and b

SAMPLE INPUT (file pprime.in)

5 500

OUTPUT FORMAT

The list of palindromic primes in numerical order, one per line.

SAMPLE OUTPUT (file pprime.out)

5711101131151181191313353373383

分析

题目意思很简单,给定一个范围a~b(一亿以内),求出该范围内的所有回文质数。这就涉及到两种特殊数字的判断,质数和回文数。
质数的判断可以按如下的代码实现:
bool isPrime(int n){if(n==0 || n==1)return false;int d=2;while(d*d<=n){if(n%d++==0)return false;}return true;}
这里注意的是,d不需要从2到n-1,到sqrt(n)就可以了。

而判断回文,在之前的题目中也使用过,可以用下面这个函数判断
bool isPalin(int n)  {  vector<int> str;while(n>0){str.push_back(n%10);n = n / 10;}int half = str.size()/2;  bool same = true;  for (int i=0;i!=half;i++)  {  same = same && str[i] == str[str.size()-i-1];  if(!same)  return false;}  if(same)  return true;  }

这样做的问题在于速度太慢了,判断的数字数量太大,在test7种b为一亿的时候,运行超时了。
因此要换一个思路来做。
首先,所有的偶数肯定不是质数,应该排除;另外,回文的判断过于复杂,应该直接生成具有回文性质的数,而不是事先有数再去判断。题目中的提示(hint2)指出,根据回文的性质,只需要枚举一般的回文数就可以了,如下:
/* generate five digit palindrome: */for (d1 = 1; d1 <= 9; d1+=2) {/* only odd; evens aren't so prime */    for (d2 = 0; d2 <= 9; d2++) {        for (d3 = 0; d3 <= 9; d3++) {    palindrome = 10000*d1 + 1000*d2 +100*d3 + 10*d2 + d1;    ... deal with palindrome ...}    }}
由于要排除所有偶数,所以d1每次加2,而不是加1。
通过上述的方法,就可以大大减少判断的数据量,提高运行速度。而除此之外,还可以根据一个数学性质来排除一部分数,即偶数长度的回文一定能被11整除,所以除了11本身,其他偶数长度的回文都不是质数,这就又可以排除掉一部分。

提交代码

/*ID: Aaron CaiPROG: pprimeLANG: C++*/#include <iostream>#include <fstream>#include <vector>#include <algorithm>#include <string>using namespace std;bool isPrime(int n){if(n==0 || n==1)return false;int d=2;while(d*d<=n){if(n%d++==0)return false;}return true;}bool isPalin(int n)  {  vector<int> str;while(n>0){str.push_back(n%10);n = n / 10;}if(str.size()%2==0)return false;int half = str.size()/2;  bool same = true;  for (int i=0;i!=half;i++)  {  same = same && str[i] == str[str.size()-i-1];  if(!same)  return false;}  if(same)  return true;  }int main(){ifstream fin("pprime.in");ofstream fout("pprime.out");int a,b;fin >> a >> b;for (int d=a;d<12;d++){if(isPrime(d))fout << d << endl;}for (int d1=1;d1<10;d1+=2){for (int d2=0;d2<10;d2++){if(isPrime(100*d1 + 10 * d2 + d1) && 100*d1 + 10 * d2 + d1>=a && 100*d1 + 10 * d2 + d1<=b)fout << 100*d1 + 10 * d2 + d1 << endl;}}for (int d1=1;d1<10;d1+=2){for (int d2 = 0;d2<10;d2++){for (int d3 =0;d3<10;d3++){if(isPrime(10000*d1 + 1000*d2 + 100 * d3 + 10*d2+d1) && 10000*d1 + 1000*d2 + 100 * d3 + 10*d2+d1>=a && 10000*d1 + 1000*d2 + 100 * d3 + 10*d2+d1<=b)fout << 10000*d1 + 1000*d2 + 100 * d3 + 10*d2+d1 << endl;}}}for (int d1=1;d1<10;d1+=2){for (int d2=0;d2<10;d2++){for (int d3=0;d3<10;d3++){for (int d4=0;d4<10;d4++){if(isPrime(1000000*d1+d1+100000*d2+10*d2 + 10000*d3+100*d3 + 1000 * d4) && 1000000*d1+d1+100000*d2+10*d2 + 10000*d3+100*d3 + 1000 * d4>=a && 1000000*d1+d1+100000*d2+10*d2 + 10000*d3+100*d3 + 1000 * d4<=b)fout << 1000000*d1+d1+100000*d2+10*d2 + 10000*d3+100*d3 + 1000 * d4 << endl;}}}}return 0;}

提交结果

TASK: pprimeLANG: C++Compiling...Compile: OKExecuting...   Test 1: TEST OK [0.051 secs, 3500 KB]   Test 2: TEST OK [0.035 secs, 3500 KB]   Test 3: TEST OK [0.057 secs, 3500 KB]   Test 4: TEST OK [0.041 secs, 3500 KB]   Test 5: TEST OK [0.035 secs, 3500 KB]   Test 6: TEST OK [0.030 secs, 3500 KB]   Test 7: TEST OK [0.049 secs, 3500 KB]   Test 8: TEST OK [0.054 secs, 3500 KB]   Test 9: TEST OK [0.092 secs, 3500 KB]All tests OK.

#include <stdio.h>#include <string.h>#include <assert.h>#include <stdlib.h>FILE *fout;long a, b;intisprime(long n){    long i;    if(n == 2)return 1;    if(n%2 == 0)return 0;    for(i=3; i*i <= n; i+=2)if(n%i == 0)    return 0;    return 1;}voidgen(int i, int isodd){    char buf[30];    char *p, *q;    long n;    sprintf(buf, "%d", i);    p = buf+strlen(buf);    q = p - isodd;    while(q > buf)*p++ = *--q;    *p = '\0';    n = atol(buf);    if(a <= n && n <= b && isprime(n))fprintf(fout, "%ld\n", n);}voidgenoddeven(int lo, int hi){    int i;    for(i=lo; i<=hi; i++)        gen(i, 1);    for(i=lo; i<=hi; i++)        gen(i, 0);}voidgenerate(void){    genoddeven(1, 9);    genoddeven(10, 99);    genoddeven(100, 999);    genoddeven(1000, 9999);}voidmain(void){    FILE *fin;    fin = fopen("pprime.in", "r");    fout = fopen("pprime.out", "w");    assert(fin != NULL && fout != NULL);    fscanf(fin, "%ld %ld", &a, &b);    generate();    exit (0);}
官方给出了好多个参考答案,但是大同小异,就不都贴出来了。
其实本题还存在一个地方可以优化,那就是大质数的判断算法,提交的代码中使用的质数判断算法对于较大的数字运行速度比较低,还有改进的空间。

THE END


0 0
原创粉丝点击