这题比较简单,看懂题意即可,主要考察:
- 素数筛法
- 进制转换
题目大意
一个用例有两个数:一个十进制数N,和进制D。如果满足以下两个条件则为Reversible Prime
- N是素数
- N转换成进制D后,将每位数字逆过来也是素数
例如:11 2
将11转换成2进制为1011,每位数字逆过来后为1101,十进制下为13。11和13都为素数,因此11是Reversible Prime。
常见错误
这题思路简单,代码写起来也非常容易。但有两点值得注意。
- 段错误。第4个用例应该是大数的边界测试,记得大数组要在函数外开辟,不然会发生段错误。
- 1不是素数。这一点容易忽略,第2个用例就是考察这一点,如果没有格外关心1的话,就容易发生错误。
代码
- 首先判断0-100000是否是素数,用一个bool notPrime[100000]数组保存,下标就代表这个数。我习惯这样预处理,这样,在需要判断时直接写成notPrime[i]即可。判断方法也很寻常,素数判断是做算法题必备的基础。
- 写了两个函数,用于将十进制转换成指定进制,用字符型数组表示,易于每位数逆转。另一个函数是得到逆转后的数对应的十进制数。很普通。
#include<stdio.h>
#include<string.h>
bool notPrime[200000];
char NR[100000];
// 预处理,对1-10^5进行标记,false为素数,true为非素数
// notPrime数组记录,下标即该数
void init()
{
for (int i = 1; i < 200000; i++)
{
notPrime[i] = false;
}
notPrime[0] = true;
notPrime[1] = true;
for (int i = 2; i < 200000; i++)
{
if (notPrime[i] == true)
{
continue;
}
for (int j = i*i; j < 200000 && j > 0; j += i)
{
notPrime[j] = true;
}
}
}
char* decimal2Radix(int x, int radix)
{
int size = 0;
if (x == 0)
{
NR[0] = '0';
NR[1] = 0;
return NR;
}
while (x > 0)
{
NR[size] = x%radix + '0';
x /= radix;
size++;
}
NR[size] = 0;
return NR;
}
int reverseRadix2Decimal(int radix)
{
int x = 0;
for (int i = 0; i < strlen(NR); i++)
{
x = x*radix + NR[i] - '0';
}
return x;
}
int main()
{
int N;
int D;
init();
while (scanf("%d%d", &N, &D) != EOF)
{
if (N < 0)
{
break;
}
decimal2Radix(N, D);
if (notPrime[N] == false && notPrime[reverseRadix2Decimal(D)] == false)
{
printf("Yes\n");
continue;
}
printf("No\n");
}
return 0;
}
最后
PAT的test case真的是方方面面都会涉及到,各种各样的边界值。光是通过了给出的示例只是最简单的一步,如果不够仔细,健壮性不够,将会非常惨…