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 <= 1000,000,000); both a and b are considered to be within the range .
InputLine 1: Two integers, a and b
OutputThe list of palindromic primes in numerical order, one per line.
Sample Input5 500Sample Output
5 7 11 101 131 151 181 191 313 353 373 383
题目是输出用户指定的两个数之间的所有既是质数又是回文数的数。
一开始的思路是顺序遍历区间中的每个数,判断是否是质数和回文数,若是则输出。
代码如下
#include <iostream> #include <math.h> using namespace std; bool isPrime(int num) { if (num % 2 == 0) return false; for (int i = 3; i <= sqrt(num); i += 2) { if (num%i == 0) return false; } return true; } bool isPalindrome(int num) { char cnum[9]; int l = 0; while (num) { cnum[l] = num % 10; num /= 10; l++; } if (l % 2 == 0) return false; for (int i = 0; i < l / 2 + 1; i++) { if (cnum[i] != cnum[l - i - 1]) return false; } return true; } int main() { int a, b; if (cin >> a >> b && a < b) { for (int i = a; i <= b; i++) { if (isPalindrome(i) && isPrime(i)) { cout << i << endl; } } } return 0; }
虽然答案没错,但是结果是Time Limit Exceed。
仔细考虑后发现,遍历所有数的方式代价太大(时间复杂度暂时没算出来)
查了一些人的做法后发现,应该采用生成回文数判断是否为质数的方式解决,因为质数的数量远远大于回文数,这样做节省了很多时间。
再加上一些细节的判断,比如偶数一定不是质数,偶数长度的回文数都能被11整除(11除外)等等。
另外看到别人的做法有生成质数表来优化,以空间换时间,我没有选择这样做。
最后的代码
// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。 #include "stdafx.h" #include <iostream> #include <math.h> int MAX = 1, MIN = 1; using namespace std; void initial(int a, int b) { while (a /= 10) MIN++; while (b /= 10) MAX++; } bool isPrime(int num) { if (num % 2 == 0) return false; for (int i = 3; i <= sqrt(num); i += 2) { if (num%i == 0) return false; } return true; } bool isPalindrome(int num) { char cnum[9]; int l = 0; while (num) { cnum[l] = num % 10; num /= 10; l++; } if (l % 2 == 0) return false; for (int i = 0; i < l / 2 + 1; i++) { if (cnum[i] != cnum[l - i - 1]) return false; } return true; } void Palindrome(int a, int b) { initial(a, b); //如果从个位数开始 if (MIN == 1) { MIN = b<10 ? b : 10; //输出10以内的结果 for (; a < MIN; a++) { if (isPrime(a)) cout << a << endl; } MIN = 2; } //如果以两位数开始 if (MIN == 2) { if (a <= 11 && b >= 11) cout << 11 << endl; MIN = 3; } //如果是偶数长度则从下一个奇数长度开始 if (!(MIN % 2)) MIN++; //对所有奇数长度的回文数判断 for (; MIN <= MAX; MIN += 2) { int num; switch (MIN) { case 3: for (int i1 = 1; i1 < 10; i1 += 2) for (int i2 = 0; i2 < 10; i2++) if (isPrime(num = i1 * 101 + i2 * 10)) { if (num < a) { continue; } if (num > b) return; cout << num << endl; } break; case 5: for (int i1 = 1; i1 < 10; i1 += 2) for (int i2 = 0; i2 < 10; i2++) for (int i3 = 0; i3 < 10; i3++) if (isPrime(num = i1 * 10001 + i2 * 1010 + i3 * 100)) { if (num < a) { continue; } if (num > b) return; cout << num << endl; } break; case 7: for (int i1 = 1; i1 < 10; i1 += 2) for (int i2 = 0; i2 < 10; i2++) for (int i3 = 0; i3 < 10; i3++) for (int i4 = 0; i4 < 10; i4++) if (isPrime(num = i1 * 1000001 + i2 * 100010 + i3 * 10100 + i4 * 1000)) { if (num < a) { continue; } if (num > b) return; cout << num << endl; } break; case 9: for (int i1 = 1; i1 < 10; i1 += 2) for (int i2 = 0; i2 < 10; i2++) for (int i3 = 0; i3 < 10; i3++) for (int i4 = 0; i4 < 10; i4++) for (int i5 = 0; i5 < 10; i5++) if (isPrime(num = i1 * 100000001 + i2 * 10000010 + i3 * 1000100 + i4 * 101000 + i5 * 10000)) { if (num < a) { continue; } if (num > b) return; cout << num << endl; } break; } } } int main() { int a, b; if (cin >> a >> b && a < b) { Palindrome(a, b); } return 0; }