PAT 甲级 1015 Reversible Primes 关于判别质数的最快方法

题目描述

在这里插入图片描述
给定一个数N,和其进制D,如果N是质数,而且ND进制下翻转,也是质数,则这个数符合要求。

输入描述

The input file consists of several test cases. Each case occupies a line which contains two integers N and D. The input is finished by a negative N.

输出描述

For each test case, print in one line Yes if N is a reversible prime with radix D, or No if not.

输入样例

73 10
23 2
23 10
-2

输出样例

Yes
Yes
No

题目分析

这道题目本身不难。如样例中的73,是一个10进制数,在10进制下翻转为37,73和37都是质数,故输出Yes;
又如23是一个2进制数,在二进制下表示为10111,在二进制下翻转为11101(29),1011111101都是质数,故也符合要求。
又如23是一个10进制数,在10进制下翻转为32,32不是质数,不符合要求。
注意: 一个数是质数与否,与它是几进制无关。但是我们更容易在10进制下判别是否是质数。
是否是质数的判别程序如下,这应该是所有方法中判别质数最快的,用到了几个定理,如大于3的质数6整除只能余1或余5等等:(原作者没考证是谁)

bool isPrime(int x) {
	if (x == 1)
		return false;
	if (x == 2 || x == 3)
		return true;
	if (x % 6 != 1 && x % 6 != 5)
		return false;
	for (int i = 5; i <= (int)sqrt(x); i += 6)
		if (x % i == 0 || x % (i + 2) == 0)
			return false;
	return true;
}

我们会在后面很多题目中用到这个模版。
关于在D进制下翻转,只需要将N除D取余,余数逆向排列是N的D进制表示,正向排列就是N的D进制下翻转,最后再转化为10进制。
完整程序如下:

#include 
#include 
#include 
using namespace std;
int Reverse(int N, int D) {
	vector<int> tmpv;
	int ans = 0;
	do {
		tmpv.push_back(N % D);
	} while (N /= D);
	for (int i = tmpv.size() - 1; i >= 0; i--)
		ans += (int)pow(D, tmpv.size() - 1 - i) * tmpv[i];
	return ans;
}
bool isPrime(int x) {
	if (x == 1)
		return false;
	if (x == 2 || x == 3)
		return true;
	if (x % 6 != 1 && x % 6 != 5)
		return false;
	for (int i = 5; i <= (int)sqrt(x); i += 6)
		if (x % i == 0 || x % (i + 2) == 0)
			return false;
	return true;
}
int main() {
	int N, D;
	scanf("%d", &N);
	while (N > 0) {
		scanf("%d", &D);
		if (isPrime(N) && isPrime(Reverse(N, D)))
			printf("Yes\n");
		else
			printf("No\n");
		scanf("%d", &N);
	}
	return 0;
}

这里有个节约运行时间的小技巧,利用&&的短路功能,如果N不是质数,就不用做翻转和判断,条件直接不成立。
当然了,这道题数据比较弱,用普通的判别质数方法也是可以通过的。

你可能感兴趣的:(PAT甲级,算法,c++)