P1218-[USACO1.5]特殊的质数肋骨 Superprime Rib

· · 个人记录

原题链接:https://www.luogu.com.cn/problem/P1218

思路:将数位一位一位加,一旦发现不是质数就跳过

例子:

5->51(跳过);

5->53(可以);

5->57(跳过);

5->59(可以)。

就是↓

    int x = m * 10 + 1;
    if (pd(x)) dfs (t + 1, x);
    x = m * 10 + 3;
    if (pd(x)) dfs (t + 1, x);
    x = m * 10 + 7;
    if (pd(x)) dfs (t + 1, x);
    x = m * 10 + 9;
    if (pd(x)) dfs (t + 1, x);

得出的规律:在开头只能添加1,2,3,5,7四个数;在中间及末尾只能添加1,3,7,9四个数

    dfs (2, 2);
    dfs (2, 3);
    dfs (2, 5);
    dfs (2, 7);

如果添加5则会变成5的倍数

代码:

#include <bits/stdc++.h>

using namespace std;

int n;

bool pd (int t) { //判断质数
    if (t == 2) return true;
    if (t % 2 == 0) return false;
    for (int i = 3; i * i <= t; i++) {
        if (t % i == 0) return false;
    }
    return true;
}

void dfs (int t, int m) {
    if (t > n) { //【恭喜这个数挑战成功】这个生成的数够n位了,输出这个数
        cout << m << endl;
        return; //返回
    }
    //中间位只能是1、3、7、9
    int x = m * 10 + 1;
    if (pd(x)) dfs (t + 1, x);
    x = m * 10 + 3;
    if (pd(x)) dfs (t + 1, x);
    x = m * 10 + 7;
    if (pd(x)) dfs (t + 1, x);
    x = m * 10 + 9;
    if (pd(x)) dfs (t + 1, x);
    return;
}

int main () {

    cin >> n;
    //第一个数是接下来要选的数位,第二个数是第一个数位中的数的选择
    //    ↓
    dfs (2, 2);
    dfs (2, 3);
    dfs (2, 5);
    dfs (2, 7);

    return 0; //结束
}