USACO Section 1.5 Superprime Rib 解题报告

题目

题目描述

超级素数的定义如下:如果有个素数我们从右往左依次去掉一位数,每次去掉一位数剩下的数仍然是素数,那么我们称这个数是超级素数。例如7331,这是一个素数,从右往左依次去掉一位数733, 73, 7,这些数字仍然是素数,所以7331是一个超级素数。
输入一个数字n (1<=n<=8),代表要找的超级素数的长度。现在需要按照从小到大排序的所有长度为n的超级素数。

样例输入

4

样例输出

2333
2339
2393
2399
2939
3119
3137
3733
3739
3793
3797
5939
7193
7331
7333
7393

解题思路

因为数据量不大所以我们直接搜索出所有的长度为n的数,然后判断是否是超级素数。在搜索时,我们可以从左往右开始枚举,每次产生一个数,我们就立刻进行素数判断。如果不是素数,那么就没必要接着枚举了,这是一个剪枝的方法。例如我们需要产生一个4位数,我现在已经产生了前两位21,判断21不是素数,所以没必要接着往下枚举了。

解题代码

/*
ID: yinzong2
PROG: sprime
LANG: C++11
*/
#define MARK
#include <iostream>
#include <cstdlib>
using namespace std;

int n;
char buf[10];

bool isPrime() {
    int val = atoi(buf);
    if (1 == val) return false;
    if (2 == val) return true;
    if (0 == (val%2)) return false;
    for (int i = 3; i*i <= val; i += 2) {
        if (0 == (val%i)) {
            return false;
        }
    }
    return true;
}

void produceSPrime(int idx) {
    if (idx == n) {
        cout << buf << endl;
        return ;
    }
    int i = 0;
    if (idx == 0) i++;
    for (; i <= 9; ++i) {
        char c = i+'0';
        buf[idx] = c;
        buf[idx+1] = '';
        if (isPrime()) { // 剪枝
            produceSPrime(idx+1);
        }
    }
}

int main() {
#ifdef MARK
    freopen("sprime.in", "r", stdin);
    freopen("sprime.out", "w", stdout);
#endif // MARK
    while (cin >> n) {
        produceSPrime(0);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/yinzm/p/7439767.html