Description
因为151 既是一个质数又是一个回文数(从左到右和从右到左是看一样的),所以151 是回文质数.
写一个程序来找出范围[a,b](5<=a<b<=2,000,000,000)间的所有回文质数;
Input
第 1 行: 二个整数 a 和 b .
Output
输出一个回文质数的列表,一行一个.
Sample Input
5 500
Sample Output
57
11
101
131
151
181
191
313
353
373
383
题解
此题原题可以打表来搞定,但数据加强后,打表显然不可以,所以我们需要分析一下。
因为在2*10^9中回文数的个数要少于素数的个数,所以我们要先枚举回文数,再判断是否为素数。
所枚举回文数满足以下条件:
1.除11外,所求回文数必须是奇数位,否则会被11整除。
2.除2,3,5,7外,所求数首位只能为1,3,7,9;
在满足以上条件的情况下进行筛选,可以用深搜的方法枚举一个数前一半的数位,如所枚举的数位abcdcba,则我们实际上真正需要枚举的是a,b,c,d。
时间复杂度为O(n!);
代码
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#define N 1000000000
using namespace std;
int n,m;
int MAXN=0;
int p[100]={
2,3,5,7,11
};
int ans[1100000];
int prime[32000];
bool used[32000];
int s[15];
int cmp(const void *x,const void *y)
{
return *(int *)x-*(int *)y;
}
void getp()
{
int num=sqrt((double)m);
for(int i=2;i<=num;i++)
{
if(!used[i])
prime[++prime[0]]=i;
for(int j=1;j<=prime[0]&&i*prime[j]<=num;j++)
{
used[i*prime[j]]=1;
if(i%prime[j]==0)
break;
}
}
}
int scan(int &x)
{
int i=0;
char c;
while((c=getchar())!=' '&&c!='\n')
x=x*10+c-'0',i++;
return i;
}
int is_prime(int num)
{
int k=num;
while(k)
s[++s[0]]=k%10,k/=10;
for(int i=2;i<=s[0];i++)
num=num*10+s[i];
memset(s,0,sizeof(s));
for(int i=1;prime[i]*prime[i]<=num&&i<=prime[0];i++)
if(num%prime[i]==0)
return 0;
return num;
}
void dfs(int x,int y,int deep,int cnt)
{
if(deep>x)
{
int z=is_prime(cnt);
if(z)
ans[++ans[0]]=z;
}
if(deep>y)
return ;
for(int i=0;i<=9;i++)
{
cnt=cnt*10+i;
if(cnt>MAXN)
return ;
dfs(x,y,deep+1,cnt);
cnt/=10;
}
}
int main()
{
int lenn=scan(n);
int lenm=scan(m);
getp();
if(m<=100)
{
for(int i=0;i<5;i++)
{
if(p[i]>=n&&p[i]<=m)
{
printf("%d\n",p[i]);
}
}
return 0;
}
if(n<=100)
{
for(int i=0;i<5;i++)
if(p[i]>=n)
printf("%d\n",p[i]);
n=101;
lenn=3;
}
if(lenn%2==1)
lenn=(lenn+1)/2;
else
lenn=lenn/2+1;
if(lenm%2==1)
lenm=(lenm+1)/2;
else
{
lenm=lenm/2;
for(int i=1;i<=lenm;i++)
MAXN=MAXN*10+9;
}
int q[20];
memset(q,0,sizeof(q));
if(!MAXN)
{
int k=m;
while(k)
q[++q[0]]=k%10,k/=10;
for(int i=q[0];i>=q[0]-lenm+1;i--)
MAXN=MAXN*10+q[i];
}
for(int i=1;i<=9;i+=2)
{
if(i!=5)
{
dfs(lenn,lenm,2,i);
}
}
qsort(ans+1,ans[0],sizeof(ans[0]),cmp);
for(int i=1;i<=ans[0];i++)
{
if(ans[i]>m)
break;
if(ans[i]>=n)
printf("%d\n",ans[i]);
}
return 0;
}