POJ 3247:回文素数--外表甜美内心却极为暴力的萝莉题

POJ 3247:回文素数--外表甜美内心却极为暴力的萝莉题

3247:回文素数
总时间限制: 5000ms 内存限制: 65536kB
描述一个数如果从左往右读和从右往左读数字是相同的,则称这个数是回文数,如121,1221,15651都是回文数。给定位数n,找出所有既是回文数又是素数的n位十进制数。(注:不考虑超过整型数范围的情况)。
输入位数n,其中1<=n<=9。
输出第一行输出满足条件的素数个数。
第二行按照从小到大的顺序输出所有满足条件的素数,两个数之间用一个空格区分。
样例输入
1
样例输出
4
2 3 5 7
OpenJudge - 3247:回文素数bailian.openjudge.cn

这题乍一眼看上去,输入值的范围不过1~9,嗯~看样子碰到了到水题,题目没有大段废话显得十分可爱,就像这样:


再看一眼评分...嗯......一半的人认为很难...好像有什么不对,又好像没什么不对。

不妨提前看一眼这道题完成后的输出结果:

注意右边的滚动条/微笑脸。


这个时候你才会发现,其实这道题本质上是这样的:

自己选的题,含着泪也要写完......


一、题意分析

题意很简单,就是找出所有n位数中,既是质数又是回文数的数字,并输出出来。


二、思路分析

需要找的数既是回文数又是质数,虽然两位都不是好惹的主,但柿子得挑软的捏,相比之下,质数这个柿子要硬一些,如果先找出高达9位数以内的质数,计算量太大必然会超时。所以不妨先确认一个思路:


先找出n位数中所有的回文数,然后再来判断其是不是质数。


大方向确认了,接下来问题是:

1、如何找出所有的回文数?

2、如何判断一个数是不是质数?


找回文数可以有两种方法:

a、找:遍历所有的n位数,检查它是否对称,不对称的排除掉,留下来的就是回文数了。

这个显然计算量也不小。

b、造:回文数,无非就是对称的数呗,先生成所有n/2位的数,然后左右对称一下,连接在一起不就是回文数了嘛。

比如要找6位数的回文数,现生成一个3位数比如123,再对称一下,生成321,连在一起就找到了一个6位回文数123321。当然如果n是基数的话,需要稍微特殊处理一下。


那如何判断一个数是不是质数呢?

Uno Whoiam:质数能帮你赚钱?| 寻找质数的最高效算法zhuanlan.zhihu.com图标

只要试除所有不大于自身的平方根的质数,保证无法被任何其中一个整除就可以了。


为什么?


假设x不是质数,那么它必然是最少两个质数的乘积,如果这两个质因数不相等,那么必然有一个质因数小于√x,如果两个质因数相等,那么这个质因数必然等于√x。


三、代码实现

考虑到最大值不会超过1^10,所以先找出所有小于1^10的平方根即100000的质数放入primenum。

const int limits=100000;
for(int i=3;i<=limits;i+=2){//find the prime number which is less than limits
        bool flag=true;
        for(int j=0;j<primenum.size()&&primenum[j]<=sqrt(i);j++){
            if(i%primenum[j]==0){
                flag=false;
                break;
            }
        }
        if(flag){
            primenum.push_back(i);
        }
    }

生成n位回文数,分别对n=1、奇数、偶数的不同情况进行不同处理。

if(n==1){
        for(int i=2;i<10;i++){
            if(PrimeJudge(i))
                dst.insert(i);
        }
    }
    else
        for(int i=pow(10,n/2-1);i<pow(10,n/2);i++){
            int palindrome;
            if(n%2==0){
                string temp=to_string(i);
                int l=0,r=(int)temp.size()-1;
                while(l<r){
                    swap(temp[l], temp[r]);
                    l++;
                    r--;
                }
                palindrome=stoi(to_string(i)+temp);
                if(PrimeJudge(palindrome))
                    dst.insert(palindrome);
            }
            else{
                for(int mid=0;mid<=9;mid++){
                    string temp=to_string(i);
                    int l=0,r=(int)temp.size()-1;
                    while(l<r){
                        swap(temp[l], temp[r]);
                        l++;
                        r--;
                    }
                    palindrome=stoi(to_string(i)+to_string(mid)+temp);
                    if(PrimeJudge(palindrome))
                        dst.insert(palindrome);
                }
            }
        }

判断一个数是不是质数:

bool PrimeJudge(int n){
    bool resault=true;
    for(int i=0;i<primenum.size()&&primenum[i]<=sqrt(n);i++){
        if(n%primenum[i]==0){
            resault=false;break;
        }
    }
    return resault;
}

大功告成!


萝莉也被调教得乖乖的呢!

四、AC code

#include <iostream>
#include <cmath>
#include <vector>
#include <set>
#include <time.h>
using namespace std;
const int limits=100000;
vector<int>primenum(1,2);

bool PrimeJudge(int n);
int main(int argc, const char * argv[]) {
    int n;
    cin>>n;
    for(int i=3;i<=limits;i+=2){//find the prime number which is less than limits
        bool flag=true;
        for(int j=0;j<primenum.size()&&primenum[j]<=sqrt(i);j++){
            if(i%primenum[j]==0){
                flag=false;
                break;
            }
        }
        if(flag){
            primenum.push_back(i);
        }
    }
    set<int>dst;
    if(n==1){
        for(int i=2;i<10;i++){
            if(PrimeJudge(i))
                dst.insert(i);
        }
    }
    else
        for(int i=pow(10,n/2-1);i<pow(10,n/2);i++){
            int palindrome;
            if(n%2==0){
                string temp=to_string(i);
                int l=0,r=(int)temp.size()-1;
                while(l<r){
                    swap(temp[l], temp[r]);
                    l++;
                    r--;
                }
                palindrome=stoi(to_string(i)+temp);
                if(PrimeJudge(palindrome))
                    dst.insert(palindrome);
            }
            else{
                for(int mid=0;mid<=9;mid++){
                    string temp=to_string(i);
                    int l=0,r=(int)temp.size()-1;
                    while(l<r){
                        swap(temp[l], temp[r]);
                        l++;
                        r--;
                    }
                    palindrome=stoi(to_string(i)+to_string(mid)+temp);
                    if(PrimeJudge(palindrome))
                        dst.insert(palindrome);
                }
            }
        }
    cout<<dst.size()<<endl;
    while(!dst.empty()){
        cout<<*dst.begin();
        dst.erase(dst.begin());
        if(!dst.empty())cout<<' ';
    }
}

bool PrimeJudge(int n){
    bool resault=true;
    for(int i=0;i<primenum.size()&&primenum[i]<=sqrt(n);i++){
        if(n%primenum[i]==0){
            resault=false;break;
        }
    }
    return resault;
}

内存:636kB 时间:399ms


PS:

广告时间啦~

理工狗不想被人文素养拖后腿?不妨关注微信公众号:


编辑于 2018-02-05