PAT 1015 Reversible Primes(进制转换+素数)

来源:互联网 发布:淘宝升钻有什么好处 编辑:程序博客网 时间:2024/06/02 01:38

题目

https://www.patest.cn/contests/pat-a-practise/1015

题意:若n为素数,且n在某个数字系统中的表示串的倒置也为素数,则称n满足可逆素数。例如,23是素数,且23在2进制下的表示10111的倒置11101即29也为素数,则23是可逆素数。给出十进制数n和目标进制d,判断n是否满足条件。

解题思路

本题思路非常简单,只需要先将n转到d进制下的表示s,再将s倒置,重新求出d进制下s对应的十进制数,判断是否为素数即可。主要涉及进制转换和素数筛法式的打表。

  1. 进制转换:之前的博客已经写过很多这样的题目,用数组和累加模拟转换即可。【由于最大n=99999,在2进制下的倒置为1F2C3=127683,所以不需要考虑大整数和long long】
  2. 筛法构造素数表,详见 POJ 2739 Sum of Consecutive Prime Numbers(素数表的应用)

第一次提交只通过了测试点1、3,剩余两个测试点考察细节:

  • 测试点4考察的是n本身不是素数要输出No
  • 以为测试点2考察输入0或者1要输出No,但实际上是n在上述倒置后变成了1,比如n=3,d=3,转换时10->01,计算出的tran=1,而0和1都不是素数。

AC代码

#include <iostream>#include <cstring>#include <cmath>using namespace std;const int maxlen = 50;const int maxN = 128000;bool visit[maxN+1];void BuildTable(int N) //素数筛法打表{    memset(visit, true, sizeof(visit));    for (int i = 4; i <= N; i += 2) //筛掉偶数,除2以外的偶数都不是素数        visit[i] = false;    for (int i = 3; i <= sqrt(N); ++i) //检查所有奇数,如果x不是质数,那么它的某个因子一定不大于sqrt(x)    {        if (visit[i])        {            int j = i<<1; //倍数至少是2            while (j <= N) //筛掉从2i~N间i的倍数            {                if (j % i == 0)                    visit[j] = false;                j += i; //j成倍增加            }        }    }}int Convert(int n, int d) //将n的d进制表示倒置后转为10进制{    int tmp[maxlen] = {0}, cnt = 0; //tmp存放d进制下的n    while (n)    {        tmp[cnt++] = n%d;        n /= d;    }    int value = 0, base = 1;    for (int i = cnt-1; i >= 0; --i) //倒置后转换到十进制    {        value += tmp[i]*base;        base *= d;    }    //cout << value << endl;    return value;}int main(){    BuildTable(maxN);    visit[0] = visit[1] = false; //测试点2    int n, d, tran;    while (cin >> n && n >= 0)    {        cin >> d;        if (n <= 1 || visit[n] == false) //本身就不是素数,测试点4        {            cout << "No" << endl;            continue;        }        tran = Convert(n, d);        //判断倒置后是否为素数        if (visit[tran]) cout << "Yes" << endl;        else cout << "No" << endl;    }    return 0;}