求5 ~ 1000000000内的回文素数

来源:互联网 发布:百度网络定位功能设置 编辑:程序博客网 时间:2024/05/20 13:09

Question:

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 .

Input

Line 1: Two integers, a and b

Output

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

Sample Input
5 500
Sample Output
5711101131151181191313353373383

解题思路:

       可能符合条件的回文数:以下称为回文数。

       设a为左界,b为右界,范围内的回文数数量很多,如果通过判断a~b之间的数是否为回文数,则会浪费大量的时间在不符合条件的数上。

       通过分析:

       1)可以证明除了11以外,不存在偶数位的回文数是素数,因为该回文数能被11整除,也就说明大于11的满足条件的回文数是奇数位,以中间数为对称轴。

       2)因大于2的素数都是奇数,故在奇数位回文数中,首位为2、4、6、8的数均不是素数。

       3)因5的任何倍数末尾为5,故在奇数位回文数中,首位为5的数均不是素数。

       4)回文数满足上述条件,故通过构造回文数比根据整数判断是否为回文数节约大多数时间。

       通过以上分析,可以得到,除<=11的回文数外,其它为奇数位,且呈现对称性。即最多为5位(99999个数),减去一半的偶数,还剩不到5W个,剩下的数中首位为0、2、4、5、6、8的数均不满足条件,回文数最多为2W个。可见通过构造回文数确实可节约大量时间。

      通过以上构造得到的回文数是满足回文素数的必要条件,但并不充分,故还需要进一步判断是否为素数,如确实为素数,则该数为回文素数。

以下为参考代码:

// PrimePalindrome.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include <iostream>#include <cmath>#include <cstdlib>#define MIN 5#define MAX 1000000000static unsigned g_iSeq = 5; // 从5开始算回文数unsigned CreatePossiblePrimePalindrome(unsigned);bool IsPrime(int iPriorPrime);int _tmain(int argc, _TCHAR* argv[]){unsigned left,right;std::cin >> left >> right;while(left < MIN || right > MAX){std::cin >> left >> right;}// 调整为奇数if (0 == left % 2){++left;}for(unsigned i = left; i < right;){i = CreatePossiblePrimePalindrome(g_iSeq);if(IsPrime(i) && i >= left && i <= right){std::cout << i << std::endl;}}system("pause");return 0;}/* 构造可能的回文素数,如给定123,则返回12321 * 原则1- 偶数位的回文不可能是素数,因为能被11整除 * 原则2- 首位为2,4,6,8不可能是素数(素数除2外都是奇数) * 原则3- 首位为5的回文不可能是素数,因为能被5整除 */unsigned CreatePossiblePrimePalindrome(unsigned n){if(n < 10){switch(n){case 5:++g_iSeq;return 5;case 6:g_iSeq = 7;return 7;case 7:case 8:case 9:g_iSeq = 10;return 11;}}// n十进制最高次项,如25876,则iCount = 4,表示10000数量级int iCount = (int)(log(n * 1.0) / log(10 * 1.0));   // n的最高位数字,如25876,则iHigh = 2int iHigh = n / (int)(pow(10 * 1.0, iCount));unsigned palindrome = 0;//最高位为2,4,5,6,8则不可能是回文素数,排除,并重新构造,如给定200,首位为2,调整为3switch(iHigh){case 2:case 4:case 6:case 8:// 如24876,本应构造为248767842,但依据原则2,所以构造为300000003g_iSeq = (iHigh + 1) * (int)pow(10 * 1.0, iCount);palindrome = g_iSeq * (int)pow(10* 1.0, iCount) + (iHigh + 1);++g_iSeq;return palindrome;case 5:// 首位为5,根据原则3和原则2,则应构造为7开头的回文数字g_iSeq = 7 * (int)pow(10 * 1.0, iCount);palindrome = g_iSeq * (int)pow(10* 1.0, iCount) + 7;++g_iSeq;return palindrome;}// 最高位满足条件,则构造回文,如12345,构造为123454321unsigned iReverse = 0; // 前n-1位的逆数和,如12345前4位的逆数和最终结果为4321palindrome = n * (int)pow(10 * 1.0, iCount); // n后面添0n /= 10; // 12345变为1234// 求逆数和,如12345,求得为4321while(n){iReverse = iReverse * 10 + n % 10;n /= 10;}++g_iSeq;return palindrome + iReverse;}bool IsPrime(int x){for(int i = 3; i * i <= x; i += 2){if (0 == x % i){return false;}}return true;}

分析:

        该算法找5到10亿内的回文素数耗时0.47s,内存消耗为1274K。耗时多花在判断回文数是否为素数。网上有现在较快的素数测试算法:Rabbin Miller测试法,可参考前文:http://blog.csdn.net/arvonzhang/article/details/8564836


原创粉丝点击