top1编程
← 返回题目
题解

【提高】素数环2

1 条题解

  • 0
    @ 2026-7-28 22:09:22
    #include<bits/stdc++.h>
    using namespace std;
    int n, a[21];//n是输入的数,a存素数环里的数字
    bool f[21];//f[i]标记数字i有没有被用过
    int c = 0;//c记录已经输出的方案数,最多出10个
    
    //判断x是不是素数
    bool p(int x) {
        if (x <= 1) return false;//1和比1小的都不是素数
        if (x == 2) return true;//2是素数
        if (x % 2 == 0) return false;//大于2的偶数不是素数
        //只拿奇数试除,节省时间
        for (int i = 3; i * i <= x; i += 2) {
            if (x % i == 0) return false;
        }
        return true;
    }
    
    //打印一组合法素数环
    void pr() {
        //没凑够10组才打印
        if (c < 10) {
            for (int i = 1; i <= n; i++) {
                cout << a[i] << " ";
            }
            cout << endl;
            c++;//打印完方案数量加1
        }
    }
    
    //k代表现在要填第k个位置
    void d(int k) {
        if (c >= 10) return;//够10个方案直接停止搜索
    
        //k大于n,所有位置全部填完
        if (k > n) {
            //圆环要求最后一位和第一位相加也是素数,合格才打印
            if (p(a[n] + a[1])) pr();
            return;
        }
    
        int s;
        if (k == 1) {
            s = 1;//第一个位置只能选1
        } else {
            s = 2;//后面位置从2开始选数
        }
    
        for (int i = s; i <= n; i++) {
            if (!f[i]) {//数字i还没被使用
                //是第一位 或者 和前一个数相加是素数,才能放进去
                if (k == 1 || p(a[k-1] + i)) {
                    a[k] = i;//把i放到第k个位置
                    f[i] = true;//标记i已经被占用
                    d(k + 1);//递归填下一个位置
                    f[i] = false;//回溯,取消标记,换别的数字尝试
                    if (c >= 10) return;//中途凑够10组直接退出
                }
            }
        }
    }
    
    int main() {
        cin >> n;
        //单独处理n=1的特殊情况
        if (n == 1) {
            cout << "1&#92;n";
            return 0;
        }
        //大于1的奇数无法组成素数环,直接结束不搜索
        if (n % 2 == 1 && n > 1) return 0;
        d(1);//从第一个位置开始回溯搜索
        return 0;
    }
    
    • 1