Problem 95 Prime Palindromes

原创 2005年04月26日 12:34:00

这个问题非常有趣,回文素数在数论里也占有一席之地,成为Palindromic Prime,或简写为Palprime。

题目的规模比之前的三道一下跳了n个数量级,达到100,000,000。不过因为只是在这个范围内做搜寻,所以并不用担心int的表示范围。但是,一亿还是很大的数字,一个个检测显然不现实,要想办法把范围缩小。首先,除了2,所有的素数都是奇数,而题目范围从5开始……Oh yeah,一下就干掉一半。俗话说好的开始是成功的一半,好兆头好兆头,hoho。接着,我们来看看回文数有什么特质:

1) 所有的个位素数都是Palprime,也就是2,3,5,7。
2) 两位回文素数只有一个,11,其他的如33,55,77等都是11的倍数。
3) 三位回文素数一共15个,分别是101,131,151,181,191,313,353,373,383,727,757,787,797,919,929。
4) 没有4位素数,实事上,偶数位的回文数全部都是11的倍数。因为一个偶数位的回文数必形如abba……E~~~我不知道怎么说了,奇数位的a+b一定等于偶数位的b+a……6位数也一样,abccba,依此类推吧-_-!。结论:11是唯一的偶位回文素数(好拗口)。
5) 五位回文素数有84个,最小的11311,最大的98689。

OK,看出一点端倪来了吧,我们只要把11单独列出来,就可以把所有偶数位数全部干掉。哦也again!再削掉一点,由于2是唯一的偶素数,所以回文素数除了2只能以奇数开头。

另外,即使在5位数10000~99999里,回文数也只有区区84个,可见回文数的数目比素数要少很多,而且,回文数是表面上就可以看出来的,而素数是自然数本身的性质,数字一大就很难直观的判断其素性。那么我们就可以不用一个个去试,而是自己动手把回文数create出来,再判断它是不是素数,如此以来,题目的规模就变得可以接受了。actually,Rob给的两个hints里也就是告诉你这么做。(想当初,Rob可没有那么kind,还给你hint…………鸡蛋!板砖!OKOK,不敢再倚老卖老了,最后一次,事不过三嘛~~~别踩,再踩就烂啦!)

现在来看看实事上我们要检查多少个数字,100,000,000是9位数,回文素数可能出现的区域实际上只有:2-9、11、101-999、10,001-99,999、1,000,001-9,999,999。每个区域内的回文数字都可以组合出来,分别是4,1,5×10,5×10×10,5×10×10×10。只有五千多个!最终的结果还要小,可见回文素数算得上是稀有族群了。

我用一个assemble函数来拼装回文数,它接受三个参数,分别是前缀1,前缀2和中间数。单独把前缀1列出来是因为回文素数开头和结尾都是奇数。重载一个双参数版本for 101-999。得到回文数后检查是不是落在要求的范围内,是不是素数,最后记得排序,因为拼装的数字并不是自然序列。

最后用三个for loop把它们包起来,你可以算一下i×j×k的积,看看和上面的组合数是不是一样的?

#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;

int assemble(int, int);
int assemble(int, int, int);
int isprime(int);

int main(){
 int a,b;
 vector<int> array;

 ifstream fin("pprime.in");
 fin>>a>>b;
 
 if(a <= 5 && b >= 5) array.push_back(5);
 if(a <= 7 && b >= 7) array.push_back(7);
 if(a <= 11 && b >= 11) array.push_back(11);
 
 for(int i = 1; i < 10; i += 2){         // prefix1 or prefix
  for(int j = 0; j < 10; ++j){        // middle
   // 1.0.1-9.9.9
   int tmp = assemble(i, j);
   if(isprime(tmp) && tmp >= a && tmp <= b) array.push_back(tmp);
   
   for(int k = 0; k < 110; ++k){   // prefix2
    // 1.0.0.0.1-9.9.9.9.9:       0<=j<=9
    // 1.10.0.01.1-9.99.9.99.9:  10<=j<=99
    // 1.00.0.00.1-9.09.9.90.9: 100<=j<=109 TRICKY! Be careful!
    tmp = assemble(i, k, j);
    if(isprime(tmp) && tmp >= a && tmp <= b) array.push_back(tmp);
   }
  }
 } 
 sort(array.begin(),array.end());
 
 ofstream fout("pprime.out");
 vector<int>::const_iterator ci = array.begin();
 for(; ci != array.end(); ++ci) fout<<(*ci)<<endl;
}

// generate a palindrome
int assemble(int prefix, int middle){
 int result = prefix * 10 + middle; 
 while(prefix){
  result = result * 10 + prefix % 10;
  prefix = prefix / 10;
 }
 return result;
}

int assemble(int prefix1, int prefix2, int middle){
 int result, prefix;
 
 if(prefix2 < 10)
  prefix = prefix1 * 10 + prefix2;
 else if(prefix2 >= 100) //generate sequence: 00-09
  prefix = prefix1 * 100 + prefix2 % 100;
 else
  prefix = prefix1 * 100 + prefix2;

 result = prefix * 10 + middle;
 while(prefix){
  result = result * 10 + prefix % 10;
  prefix = prefix / 10;
 }
 return result;
}

int isprime(int i){
 if(i == 2) return 1;
 if(!(i%2)) return 0;
 for(int divisor = 3; divisor*divisor <= i; divisor += 2){
  if(!(i%divisor)) return 0;
 }
 return 1;
}

参考:http://hk.geocities.com/goodprimes/OBack.htm

USACO 1.5 Prime Palindromes

Prime Palindromes The number 151 is a prime palindrome because it is both a prime number and a ...

USACO-Section 1.5 Prime Palindromes(Miller-Rabin)

由于USACO挂了,只得在NOCOW看题,没想到HINT原本是隐藏的,直接看了HINT后逃离不了这种思路。。。 由于回文数比质数还少,所以先构造回文数,再判断其是否为素数 题目比较简单,所以学习一下M...

USACO-Section1.5 Prime Palindromes【暴力枚举】

题目描述:因为151既是一个质数又是一个回文数(从左到右和从右到左是看一样的),所以 151 是回文质数。 写一个程序来找出范围[a,b](5 ...
  • tjj1998
  • tjj1998
  • 2017年06月02日 23:05
  • 77

USACO-Section1.5 Prime Palindromes

USACO-Section1.5 Prime Palindromes

USACO Section 1.5 Prime Palindromes

题意: 输入a和b  求 a和b之间所有既是素数同时又有回文性质的数  从小到大输出 思路: 如果枚举a到b之间所有的数再判断素数和回文那么复杂度会比O(n)还大  本题O(n)都会跪 ...

USACO 1.5 Prime Palindromes (打表查询)

#include #define DEBUG 1 #define TESTCASES 9 #define ABS(x) ( (x) > 0 ? (x) : -(x) ) #define PRECISI...

[搜索]USACO-1.5-Prime Palindromes

Prime Palindromes The number 151 is a prime palindrome because it is both a prime number and a pa...

USACO-cha1-sec1.5 Prime Palindromes

Prime Palindromes The number 151 is a prime palindrome because it is both a prime number and a pa...

USACO-Section1.5 Prime Palindromes

2017-07-19题目大意: 因为151既是一个质数又是一个回文数(从左到右和从右到左是看一样的),所以 151 是回文质数。 写一个程序来找出范围[a,b](5 ...
  • Jane_96
  • Jane_96
  • 2017年07月19日 10:45
  • 83

Prime Palindromes(回文素数)

Problem Description The number 151 is a prime palindrome because it is both a prime number and a pal...
  • deaidai
  • deaidai
  • 2017年03月18日 21:49
  • 547
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Problem 95 Prime Palindromes
举报原因:
原因补充:

(最多只允许输入30个字)