题目描述
给定一个数N,和其进制D,如果N是质数,而且N在D进制下翻转,也是质数,则这个数符合要求。
输入描述
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),10111和11101都是质数,故也符合要求。
又如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 <iostream>
#include <vector>
#include <cmath>
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不是质数,就不用做翻转和判断,条件直接不成立。
当然了,这道题数据比较弱,用普通的判别质数方法也是可以通过的。