题目描述
因为 151 既是一个质数又是一个回文数(从左到右和从右到左是看一样的),所以 151 是回文质数。
写一个程序来找出范围 [a,b] (5≤a<b≤100,000,000)( 一亿)间的所有回文质数。
输入格式
第 1 行: 二个整数 a 和 b .
输出格式
输出一个回文质数的列表,一行一个。
输入输出样例
输入 #1
5 500
输出 #1
5
7
11
101
131
151
181
191
313
353
373
383
思路过程
这题要么打表,要么创回文数。打表循环那些太烦了,当然得选后者了。
基本思路就是:创一个k位的回文数;再判断在不在给的范围里,小的跳过,大的推出;然后判断是不是质数。
然后开始考虑特判:
1.一位数的回文质数只剩5和7了;
2.两位数的回文质数只剩11了;
3.偶数位(除了两位数)是没有回文质数的,证明也很容易:
假设六位数存在回文质数abccba,而abccba可以被分为a0000a+b00b0+cc00,这三个数都是11的倍数,其他偶数位数也是一样的。
4.9位数只有一亿,也不用判了
#include <bits/stdc++.h>
#include <cmath>
using namespace std;
int l,r,x,y;//l,r是范围,x,y是它们的位数
int a[10];//存创造出来的数
bool f=1;//用来作为是否已经超范围,需要退回去的标志
bool isprime(int x)//判断是不是质数
{
if(x<2) return false;
if(x==2) return true;
for(int i=2;i*i<=x;i++)
{
if(x%i==0) return false;
}
return true;
}
int length(int x)//判断l,r的位数
{
int count=0,s=x;
while(s>0)
{
s/=10;
count++;
}
return count;
}
void Plainchorme(int x,int k)
//x表示已经枚举到的位置,k是总位数
{
if(x==(k+1)/2)//如果已经到了正中间的位置
{
for(int i=k;i>x;i--)//把另一边完善
a[i]=a[k-i+1];
int fig=0;
for(int i=1;i<=k;i++)
{
fig=fig*10+a[i];//再把这个数展到fig
}
if(fig<l) return;//判断这个回文数在不在范围内
if(fig>r)
{
f=false;
return;
}
if(isprime(fig))//在的话判断是否为质数
printf("%d\n",fig);
return;
}
int j;
if(x)//if(x!=0)
j=0;
else j=1;
//判断进行到了哪一位,最高位要从1开始,其余位从0开始
for(int i=j;i<=9;i++)
{
if(f==false) return;
//如果上个数已经超范围的话,退回去
a[x+1]=i;
Plainchorme(x+1,k);//开始创下一个回文数
}
return;
}
int main()
{
int i;
scanf("%d%d",&l,&r);
x=length(l);
y=length(r);
for(i=x;i<=y;i++)
{
if(i==1)
{
if(l<=5&&r>=5) printf("5\n");
if(l<=7&&r>=7) printf("7\n");
continue;
}
if(i==2)
{
if(l<=11&&r>=11)
printf("11\n");
continue;
}
if(i%2==0) continue;
if(i==9) break;
f=true;//每次要把f重新置1
Plainchorme(0,i);
}
return 0;
}