哥德巴赫猜想(北理工2018年考研复试机试题)

哥德巴赫猜想

任何一个大于2的偶数均可表示为两个素数之和。输入m, n(6<=m<=n<=50),则把[m, n]内的所有偶数表示成两个素数之和的形式。输出这些素数及其出现的次数,输出次序按照素数出现的次数从多到少输出;若出现次数相同,按照素数从大到小输出;若偶数有多种素数相加形式,则把所有的情况都输出,每种情况占一行。

测试用例:

输入:8 9    输出:5 1 3 1

输入:9 10  输出:5 2

                                 7 1 3 1

输入:14 15 输出:7 2

                                   11 1 3 1

输入:8 10   输出:5 3 3 1

                                   3 2 7 1 5 1

代码思路:

  1. 判断素数

    • 函数 is_prime 通过试除法判断一个数是否为素数。对于输入 num,从 2 遍历到 num​,若存在能整除的数则返回 false,否则返回 true

  2. 生成偶数的素数对

    • 输入区间 [m,n],遍历每个数,筛选出所有偶数(跳过奇数)。

    • 对每个偶数 i,遍历 j 从 2 到 i/2,若 j 和 i−j 均为素数,则将这对数 (j,i−j) 存入 map>> mp 中,键为偶数 i,值为所有可能的素数对。

  3. DFS生成所有组合

    • 使用深度优先搜索(DFS)递归生成所有可能的素数对组合。

    • 递归函数 dfs 遍历每个偶数,依次选择其一个素数对,存入当前组合 current 中。当处理完所有偶数时,将完整组合存入 res

    • 回溯机制:选择某个素数对后递归处理下一个偶数,完成后撤销选择(pop_back),继续尝试其他分支。

  4. 输出结果

    • 遍历所有组合 res,按顺序输出每个偶数的素数对,格式为 偶数 = 素数1 + 素数2,多个素数对用逗号分隔。

代码如下:

#include 
#include 
#include 
#include 
using namespace std;

// 判断是否为素数
bool is_prime(int num) {
    if (num <= 1) return false;
    for (int i = 2; i * i <= num; i++) {
        if (num % i == 0) return false;
    }
    return true;
}

// 存储每个偶数的所有素数对
map > > mp;
// 存储所有可能的组合
vector > > res;

// DFS递归生成所有组合
void dfs(int index, vector >& current, const vector& evens) {
    if (index == evens.size()) {  // 递归终止条件:处理完所有偶数
        res.push_back(current);
        return;
    }

    int even = evens[index];
    if (mp[even].empty()) {       // 如果当前偶数没有素数对,跳过
        dfs(index + 1, current, evens);
        return;
    }

    // 遍历当前偶数的所有素数对
    for (vector >::const_iterator it = mp[even].begin(); it != mp[even].end(); ++it) {
        const pair& p = *it;  // 获取当前素数对
        current.push_back(p);           // 选择当前素数对
        dfs(index + 1, current, evens); // 递归处理下一个偶数
        current.pop_back();             // 回溯,撤销选择
    }
}

int main() {
    int m, n;
    cin >> m >> n;

    // 生成区间内的所有偶数及其素数对
    vector evens;
    for (int i = m; i <= n; i++) {
        if (i % 2 != 0) continue;  // 跳过奇数
        evens.push_back(i);       // 将偶数加入 evens 向量
        for (int j = 2; j <= i / 2; j++) {
            if (is_prime(j) && is_prime(i - j)) {
                // 使用 make_pair 创建 pair 对象并加入 mp[i]
                mp[i].push_back(make_pair(j, i - j));
            }
        }
    }

    // DFS遍历所有可能的组合
    vector > current;
    dfs(0, current, evens);

    // 输出结果
    for (vector > >::const_iterator comb_it = res.begin(); comb_it != res.end(); ++comb_it) {
        const vector >& combination = *comb_it;  // 获取当前组合
        for (size_t i = 0; i < combination.size(); i++) {
            int even = evens[i];  // 获取当前偶数
            const pair& p = combination[i];  // 获取当前素数对
            cout << even << " = " << p.first << " + " << p.second;
            if (i != combination.size() - 1) cout << ", ";
        }
        cout << endl;
    }

    return 0;
}

其他:

本题作为北理复试机试中唯一一道难题,网上基本搜不到明确的答案,ai也通通阵亡于离谱的输出格式,索性自己写一个,希望大家能看懂。最后的一点输出格式调整大家自己想吧。

注:

本题难度偏大,按照近些年的机试趋势,不可能再考这么难的题,酌情训练。

你可能感兴趣的:(算法,C++,深度优先,图论)