计蒜客T1986素数回文(对于素数判定的快速方法)

[计蒜客]T1986素数回文

一、题目描述

蒜头君对既是素数又是回文的数特别感兴趣。比如说 151 既是素数又是个回文数。回文数是指从左到右读和从右到左读都一样的数。
现在小王想要你帮助他找出某个范围内的素数回文数,请你写个程序找出 a 跟 b 之间(包含 a 和 b)满足条件的数。
输入格式
输入 a 和 b(2≤a 输出格式
按从小到大输出 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
#include
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

你可能感兴趣的:(算法,算法,c++,开发语言)