[计蒜客]T1986素数回文
一、题目描述
蒜头君对既是素数又是回文的数特别感兴趣。比如说 151 既是素数又是个回文数。回文数是指从左到右读和从右到左读都一样的数。
现在小王想要你帮助他找出某个范围内的素数回文数,请你写个程序找出 a 跟 b 之间(包含 a 和 b)满足条件的数。
输入格式
输入 a 和 b(2≤a<b≤100,000,000)。
输出格式
按从小到大输出 a,b 之间所有满足条件的素数回文数,一个数占一行。
格式说明
输出时每行末尾的多余空格,不影响答案正确性
样例输入
2 200
样例输出
2
3
5
7
11
101
131
151
181
191
二、解题思路
1、判定素数
一种简单常见的素数判定方式如下:
bool isPrime(int n)
{
for(int i=2;i<=sqrt(n);i++)
if(n%i==0)
return false;
return true;
}
但是如果使用此种判定素数方法,由于b的取值最大能够取到
1
0
8
10^8
108,即一亿,使用此种判定素数方式可能会导致程序超时无法拿到AC结果,因此此处我们使用另一种优化后的判定素数算法
代码实现如下:
bool isPrime(int n)
{
if (n <= 3)//当n不大于3时只有1不是素数
return n > 1;
if (n % 6 != 1 && n % 6 != 5)//只有6i+1和6i+5可能是素数
return false;
for (int i = 5; i <= sqrt(n); i += 6)
{
if (n % i == 0 || n % (i + 2) == 0)
return false;
}
return true;
}
6i+1与6i+5
所有自然数均可表示为6i 6i+1 6i+2 6i+3 6i+4 6i+5
表示 | 是否可能为素数 |
---|---|
6i | 不可能,为2的倍数 |
6i+1 | 可能 |
6i+2 | 不可能,为2的倍数 |
6i+3 | 不可能,为3的倍数 |
6i+4 | 不可能,为2的倍数 |
6i+5 | 可能 |
2、判定回文
一种常见的回文数算法如下:
bool isPalindrome(int n)
{
int x = 0;
int y = n;
while (y > 0)
{
x = x * 10 + y % 10;
y = y / 10;
}
if (x == n)
return true;
else
return false;
}
x从0开始,y从n开始。
x每次乘以10(相当于向前移一位)再加y的尾数,y每次除以10(相当于去掉尾数)。
当y一直除到0时,x被重新构造成为n的逆序
如果重新构造的x等于n,则是回文数,否则不是回文数
接下来只要在主函数中输入a与b的值并且遍历区间中的每一个值,调用isPrime()函数和isPalindrome()函数判定是否回文且是否是素数即可
三、代码实现
最终总体代码如下:
#include<iostream>
#include<math.h>
using namespace std;
bool isPrime(int n)
{
if (n <= 3)//当n不大于3时只有1不是素数
return n > 1;
if (n % 6 != 1 && n % 6 != 5)//只有6i+1和6i+5可能是素数
return false;
for (int i = 5; i <= sqrt(n); i += 6)
{
if (n % i == 0 || n % (i + 2) == 0)
return false;
}
return true;
}
bool isPalindrome(int n)
{
int x = 0;
int y = n;
while (y > 0)
{
x = x * 10 + y % 10;
y = y / 10;
}
if (x == n)
return true;
else
return false;
}
int main()
{
int a, b;
cin >> a >> b;
for (int i = a; i <= b; i++)
{
if (isPalindrome(i) && isPrime(i))
cout << i << endl;
}
return 0;
}
——Written by Ryan_LuoYuxuan