题目描述:
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);
}
*/