题目描述
因为 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
本题暴力的话毫无疑问会超时,——因为俺就是暴力WA了四次呜呜;
首先是 判断回文数的模板 可以用wihile来实现(其实就是相当于把一个整数反转过来)
bool judge(int n)
{
int n_2=n;//记录n的初始值
int n_1=0;
while(n)
{
n_1*=10;
n_1+=n%10;
n/=10;
}
if(n_1==n_2) return true;//判断是否是回文数
else return false;
}
由于题目的数据范围非常庞大,所以可以采取打表的做法(但是俺不会);
所以想了一个别的写法(看了少数的题解)才发现这个做法
那就是::::线性筛法(复杂度是O(n))
#include<iostream>
using namespace std;
const int N = 1000010;
int n;
int prime[N], cnt;
bool st[N];
void select_prime(int n)
{
for(int i = 2; i <= n ;i++){
if(!st[i]) {
prime[cnt++] = i;
}
for(int j = 0; prime[j] <= n / i ; j ++) //从小到大枚举所有的质数
{
st[prime[j] * i] = true;
if(i % prime[j] == 0) break; //prime[j]一定是i的最小质因子, 因此只会筛选一次,线性的
}
}
}
int main(){
cin >> n;
select_prime(n);
printf("%d\n", cnt);
return 0;
}
上面的就是线性筛法的实现代码;
AC代码如下
#include<iostream>
#include<cstdio>
#define N 10000005
using namespace std;
int primes[N];
bool st[N];
int isprime[N];
bool judge(int n)
{
int n_2=n;
int n_1=0;
while(n)
{
n_1*=10;
n_1+=n%10;
n/=10;
}
if(n_1==n_2) return true;
else return false;
}
int main()
{
int l,r;
scanf("%d%d",&l,&r);
int cnt=0;
if(r>10000000) r=10000000;
for(int i=2;i<=r;i++)
{
if(!isprime[i]) primes[cnt++]=i,st[i]=1;
for(int j=0;j<cnt&&i*primes[j]<=r;j++)
{
isprime[i*primes[j]]=i;
if(i%primes[j]==0) break;
}
}
for(int i=l;i<=r;i++)
{
if(i>10000000) break;
if(judge(i)&&st[i]) printf("%d\n",i);
}
}
本题来自USACO ;
题干来自洛谷P自洛谷P1217;
谢谢阅读!!!