题目描述:
http://ace.delos.com/usacoprob2?a=natOyh2BvAP&S=pprime
因为151既是一个质数又是一个回文数(从左到右和从右到左是看一样的),所以 151 是回文质数。
写一个程序来找出范围[a,b](5 <= a < b <= 100,000,000)( 一亿)间的所有回文质数;
其实这是水题一道,之所以想总结一下,是想揭露一下自己丑陋的实现代码。
这道题目其实是让找[a,b]区间段的回文质数,比如151,就是一个回文质数。但是b的可取值给的很大,高达1000 000 000,所以不能直接一个一个的去测试,因为从1一直循环到1000 000 000 一定会超时的,所以就得去构造,也就是说,自己构造出指定区间的回文数,然后在检测其是否为质数。
如果去构造的话,比如构造12344321这样的额回文数,就是1*10000001+2*1000010+3*100100+4*11000 = 12344321.。
在代码实现上,可以发现,长度不同的回文数,其具体实现代码不一样。。。想了半天也想不到能揉和到一起的实现代码,没办法,就写了九个子函数,然后用函数指针数组实现的,代码如下,其形极其丑陋无比。尤其是做完后看了标准答案之后,更加得吸取教训。
标准答案的精妙之处在于,他在构造回文数的时候,是先在数字区间便利,然后转成字符串,然后对称构造回文数,然后再将字符串转化为数。其中两个库子函数,我平时用的很少,再次记录一下:
将int转为char *类型的函数:sprintf(buf, "%d", i);
将char*转化为int 类型的函数为: n = atol(buf);
我的代码如下:
#include<iostream> #include<fstream> #include<vector> using namespace std; int a,b; int len(int x); bool isPrime(int x); bool isIn(int x); void gen1();void gen2();void gen3();void gen4();void gen5(); void gen6();void gen7();void gen8();void gen9(); void (*gen[10])() = {gen1,gen1,gen2,gen3,gen4,gen5,gen6,gen7,gen8,gen9}; vector<int>results; ifstream infile; ofstream outfile; int main(){ infile.open("pprime.in"); outfile.open("pprime.out"); //cin>>a>>b; infile>>a>>b; int lenA = len(a); int lenB = len(b); for(int i=lenA;i<=lenB;i++) (*gen[i])(); for(int i=0;i<results.size();i++) //cout<<results[i]<<endl; outfile<<results[i]<<endl; return 0; } int len(int x){ int re = 0; while(x){ re++; x/=10; } return re; } bool isPrime(int x){ for(int i=2;i*i<=x;i++) if(x%i == 0) return false; return true; } bool isIn(int x){ return ((x>=a)&&(x<=b)); } void dealRes(int temp){ if(isIn(temp) && isPrime(temp)) results.push_back(temp); } void gen1(){ if(isIn(5)) results.push_back(5); if(isIn(7)) results.push_back(7); } void gen2(){ int temp; for(int d1=1;d1<=9;d1+=2){ temp = d1*11; dealRes(temp); } } void gen3(){ int temp; for(int d1=1;d1<=9;d1+=2) for(int d2=0;d2<=9;d2++){ temp = d1*101+d2*10; dealRes(temp); } } void gen4(){ int temp; for(int d1=1;d1<=9;d1+=2) for(int d2=0;d2<=9;d2++){ temp = d1*1001+d2*110; dealRes(temp); } } void gen5(){ int temp; for(int d1=1;d1<=9;d1+=2) for(int d2=0;d2<=9;d2++) for(int d3=0;d3<=9;d3++) { temp = d1*10001+d2*1010+d3*100; dealRes(temp); } } void gen6(){ int temp; for(int d1=1;d1<=9;d1+=2) for(int d2=0;d2<=9;d2++) for(int d3=0;d3<=9;d3++) { temp = d1*100001+d2*10010+d3*1100; dealRes(temp); } } void gen7(){ int temp; for(int d1=1;d1<=9;d1+=2) for(int d2=0;d2<=9;d2++) for(int d3=0;d3<=9;d3++) for(int d4=0;d4<=9;d4++) { temp = d1*1000001+d2*100010+d3*10100+d4*1000; dealRes(temp); } } void gen8(){ int temp; for(int d1=1;d1<=9;d1+=2) for(int d2=0;d2<=9;d2++) for(int d3=0;d3<=9;d3++) for(int d4=0;d4<=9;d4++) { temp = d1*10000001+d2*1000010+d3*100100+d4*11000; dealRes(temp); } } void gen9(){ int temp; for(int d1=1;d1<=9;d1+=2) for(int d2=0;d2<=9;d2++) for(int d3=0;d3<=9;d3++) for(int d4=0;d4<=9;d4++) for(int d5=0;d5<=9;d5++) { temp = d1*100000001+d2*10000010+d3*1000100+d4*101000+d5*10000; dealRes(temp); } }
官方代码:
#include <stdio.h> #include <string.h> #include <assert.h> #include <stdlib.h> FILE *fout; long a, b; int isprime(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; } void gen(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); } void genoddeven(int lo, int hi) { int i; for(i=lo; i<=hi; i++) gen(i, 1); for(i=lo; i<=hi; i++) gen(i, 0); } void generate(void) { genoddeven(1, 9); genoddeven(10, 99); genoddeven(100, 999); genoddeven(1000, 9999); } void main(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); } */