题目描述
英文
中文大意
给定任意两个正整数 N
(<105) D
(1 < D <= 10)
请指出它是否是基于进制D 的 逆转素数
逆转素数:本身是素数,转换为D进制后,逆转,再转换为10进制,观察是否还是素数
输入
每行输入包括 N, D
,输入结束于一个 负数N
输出
对于每行的输入用例,如果是 逆转素数,输出 Yes
,否则输出No
样例
思路分析
- 判断素数的方法,能否效率更高?
- 进制转换时注意 顺序 和 起始位置
判断素数的方法:
#include <math.h>
// 常用方法
bool is_prime(int n) {
if (n <= 3) {
return n > 1;
}
int s = (int)sqrt(n);
for (int i = 2;i <= s;i++) {
if (n % i == 0)
return false;
}
return true;
}
// 通过数学方法 `6x-1` 与 `6x+1` 判断
bool is_prime_with_math(int n) {
if (n <= 3) {
return n > 1;
}
// 不在6的倍数两侧的一定不是素数
if (n % 6 != 1 && n % 6 != 5) {
return false;
}
int s = (int)sqrt(n);
for (int i = 5;i <= s;i+=6) {
// 为何是 i 和 i+2 呢?因为满足条件的必定是 6i-1 或 6i+1
// 6i+2 与 6i+4 都是偶数, 6i+3 必定是 3 的倍数
// 所以只用检查 6i-1 与 6i+1
if (n % i == 0 || n % (i + 2) == 0) {
return false;
}
}
}
code
#include <iostream>
#include <math.h>
using namespace std;
// 判断一个数是否为素数
bool is_prime(int n) {
if (n <= 3) {
return n > 1;
}
int s = (int)sqrt(n);
for (int i = 2;i <= s;i++) {
if (n % i == 0)
return false;
}
return true;
}
bool is_reversible_prime(int N, int D) {
if (is_prime(N)) {
// 记录存储的位数, 顺便充当指针
int p = 0;
// 记录转换后的素数
int res = 0;
// N < 10^5
int revD[10000] = { 0 };
// 譬如 N:19 D:2
// 11001 实际上19的二进制转换是 10011
while (N > 0) {
revD[p] = N % D;
N /= D;
p++;
}
for (int i = p-1;i >= 0;i--) {
res += revD[i] * (int)(pow(D, p-1-i));
}
if (is_prime(res)) {
return true;
} else {
return false;
}
} else {
return false;
}
}
int main() {
int N, D;
scanf("%d%d", &N, &D);
while(N > 0) {
if (is_reversible_prime(N, D)) {
printf("Yes\n");
}
else {
printf("No\n");
}
scanf("%d%d", &N, &D);
}
return 0;
}