【困难】算法nodeJs:素数伴侣

145 阅读2分钟

定义两个正整数 a 和 b 是“素数伴侣”,当且仅当 a+b 是一个素数。 现在,密码学会邀请你设计一个程序,从给定的 n 个正整数 {a1​,a2​,…,an​} 中,挑选出最多的“素数伴侣”,你只需要输出挑选出的“素数伴侣”对数。保证 n 为偶数,一个数字只能使用一次。

输入描述:

第一行输入一个正偶数 n(2≦n≦100) 代表数字个数。
第二行输入 n 个正整数 a1​,a2​,…,an​(1≦ai​≦3×104) 代表给定的数字。

image.png

输出描述:

输出一个整数,代表最多可以挑选出的“素数伴侣”的数量。

示例

输入:4

2 5 6 13

输出:2

说明: 在这个样例中,2 和 5 可以组成一对素数伴侣,6 和 13 也可以组成一对素数伴侣。因此,最多可以挑选出 2 对素数伴侣。

const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;

void (async function () {
    while ((line = await readline())) {
        let n = Number(line);
        let odd = [];
        let even = [];
        // 把数据分成奇数和偶数,因为奇数+偶数才能得出奇数,所有素数除了2以外都是奇数
        (await readline()).split(" ").forEach((v) => {
            v = Number(v);
            if (v % 2 === 0) {
                even.push(v);
            } else {
                odd.push(v);
            }
        });

        if (odd.length == 0 || even.length == 0) {
            console.log(0);
            return;
        }
        // 遍历并找到所有素数伴侣
        const map = [];
        for (let i = 0; i < odd.length; i++) {
            map[i] = new Array(even.length);
            for (let j = 0; j < even.length; j++) {
                map[i][j] = isPrime(odd[i] + even[j]);
            }
        }

        let count = 0;
        let usedEven = []; // 存放每次遍历里面的偶数下标,防止无限递归
        let matchArr = []; // matchArr[j]存放偶数j对应的奇数下标i
        for (let i = 0; i < odd.length; i++) {
            if (isMach(i)) {
                count++;
                usedEven = [];
            }
        }

        console.log(count);

        function isMach(i) {
            for (let j = 0; j < even.length; j++) {
                // i、j对应的奇偶数的话如果不是素数或者当前偶数下标在这次isMach递归中已经使用过则直接跳过当前循环
                if (!map[i][j] || usedEven[j]) continue;
                usedEven[j] = true;
                // 如果j没有匹配过,或者原来跟j匹配的奇数matchArr[j]能找到其他匹配
                if (matchArr[j] === undefined || isMach(matchArr[j])) {
                    matchArr[j] = i;
                    return true;
                }
            }
            return false;
        }
        function isPrime(n) {
            let res = true;
            for (let i = 2; i * i <= n; i++) {
                if (n % i === 0) {
                    res = false;
                }
            }
            return res;
        }
    }
})();