2023-03-25:若两个正整数的和为素数,则这两个正整数称之为"素数伴侣"。
给定N(偶数)个正整数中挑选出若干对,组成"素数伴侣",
例如有4个正整数:2,5,6,13,
如果将5和6分为一组的话,只能得到一组"素数伴侣",
如果将2和5、6和13编组,将得到两组"素数伴侣",
这是得到"素数伴侣"最多的划分方案。
输入:
有一个正偶数 n ,表示待挑选的自然数的个数。后面给出 n 个具体的数字。
输出:
输出一个整数 K ,表示最多能找出几对"素数伴侣"。
数据范围: 1 <= n <= 100, 2 <= val <= 30000。
来自华为。

答案2023-03-05:

用二分图最大匹配来解决。具体步骤如下:

将所有数字看作二分图的左右两部分节点,如果两个节点的和是一个素数,则在它们之间连接一条边。

使用 KM 算法求解二分图的最大匹配。最大匹配的结果就是最多能找到多少对“素数伴侣”。

这里需要注意的是,KM算法的时间复杂度为 O(n^3),但本题数据范围比较小,因此可以通过。

rust代码如下:

// 构造邻接矩阵
fn matrix(arr: &[i32], n: usize) -> Vec<Vec<i32>> {
// 判断是否是素数的函数
let is_prime = |num| (2..(num as f64).sqrt() as i32 + 1).all(|i| num % i != 0);
let mut ans = vec![vec![0; n]; n];
for i in 0..n {
for j in 0..n {
ans[i][j] = if is_prime(arr[i] + arr[j]) { 1 } else { 0 };
}
}
ans
} // KM算法实现求解最大匹配
fn km(graph: &[Vec<i32>]) -> i32 {
let n = graph.len();
let invalid = i32::MAX;
let mut match_ = vec![-1; n]; // 记录匹配情况的数组,初始值为-1表示没有匹配
let mut lx = vec![-invalid; n]; // 左部点的标号
let mut ly = vec![0; n]; // 右部点的标号
let mut x = vec![false; n]; // 记录左部点是否被访问
let mut y = vec![false; n]; // 记录右部点是否被访问
let mut slack = vec![invalid; n]; // 记录松弛量
// 初始化左部点的标号为与之相连的右部点的边权的最大值
for i in 0..n {
for j in 0..n {
lx[i] = lx[i].max(graph[i][j]);
}
}
// 在未匹配的情况下,进行增广
while let Some(from) = (0..n).find(|i| match_[*i] == -1) {
slack.fill(invalid); // 初始化松弛量为无穷大
x.fill(false); // 初始化左部点为未访问
y.fill(false); // 初始化右部点为未访问
// 在当前的未匹配节点进行增广
while !dfs(
from,
&mut x,
&mut y,
&lx,
&ly,
&mut match_,
&mut slack,
graph,
) {
// 如果无法找到增广路,则更新标号
let d = slack
.iter()
.enumerate()
.filter(|&(i, &s)| !y[i] && s != invalid)
.map(|(i, _)| i)
.min()
.unwrap();
for i in 0..n {
if x[i] {
lx[i] -= slack[d];
}
if y[i] {
ly[i] += slack[d];
}
}
x.fill(false);
y.fill(false);
}
}
// 计算所有边的权值和
lx.iter().sum::<i32>() + ly.iter().sum::<i32>()
} // DFS函数实现增广
fn dfs(
from: usize,
x: &mut [bool],
y: &mut [bool],
lx: &[i32],
ly: &[i32],
match_: &mut [i32],
slack: &mut [i32],
graph: &[Vec<i32>],
) -> bool {
let n = graph.len();
x[from] = true; // 记录左部点为已访问
for to in 0..n {
if !y[to] {
// 如果右部点没有被访问
let d = lx[from] + ly[to] - graph[from][to]; // 计算松弛量
if d != 0 {
// 如果松弛量不为0,则更新松弛量
slack[to] = slack[to].min(d);
} else {
// 如果松弛量为0,则进行增广
y[to] = true; // 标记右部点为已访问
if match_[to] == -1 || dfs(match_[to] as usize, x, y, lx, ly, match_, slack, graph)
{
// 如果当前右部点没有匹配,或者能够寻找到增广路,则进行匹配,并返回true
match_[to] = from as i32;
return true;
}
}
}
}
false // 没有找到增广路,返回false
} // 主函数
fn main() {
// 示例数据1
println!("{}", km(&matrix(&[2, 5, 6, 13], 4)) / 2); // 输出结果为2 // 示例数据2
println!("{}", km(&matrix(&[3, 6], 2)) / 2); // 输出结果为0
}

2023-03-25:若两个正整数的和为素数,则这两个正整数称之为“素数伴侣“。 给定N(偶数)个正整数中挑选出若干对,组成“素数伴侣“, 例如有4个正整数:2,5,6,13, 如果将5和6分为一组的的更多相关文章

  1. [2019.03.25]Linux中的查找

    TMUX天下第一 全世界所有用CLI Linux的人都应该用TMUX,我爱它! ======================== 以下是正文 ======================== Linu ...

  2. Java基础-多线程编程-1.随便选择两个城市作为预选旅游目标。实现两个独立的线程分别显示10次城市名,每次显示后休眠一段随机时间(1000ms以内),哪个先显示完毕,就决定去哪个城市。分别用Runnable接口和Thread类实现。

    1.随便选择两个城市作为预选旅游目标.实现两个独立的线程分别显示10次城市名,每次显示后休眠一段随机时间(1000ms以内),哪个先显示完毕,就决定去哪个城市.分别用Runnable接口和Thread ...

  3. @有两个含义:1,在参数里,以表明该变量为伪参数 ,在本例中下文里将用@name变量代入当前代码中2,在字串中,@的意思就是后面的字串以它原本的含义显示,如果不

    @有两个含义:1,在参数里,以表明该变量为伪参数 ,在本例中下文里将用@name变量代入当前代码中 2,在字串中,@的意思就是后面的字串以它原本的含义显示,如果不加@那么需要用一些转义符\来显示一些特 ...

  4. 有两个指针pa,pb分别指向有两个数,a,b,请写一个函数交换两个指针的指向,也就是让pa指向b,让pb指向a

    题目:有两个指针pa,pb分别指向有两个数,a,b,请写一个函数交换两个指针的指向,也就是让pa指向b,让pb指向a,具体实现如下: #include<stdlib.h> #include ...

  5. 如何从两个List中筛选出相同的值

    问题 现有社保卡和身份证若干,想要匹配筛选出一一对应的社保卡和身份证. 转换为List socialList,和List idList,从二者中找出匹配的社保卡. 模型 创建社保卡类 /** * @a ...

  6. 在编写wpf界面时候中出现如下错误: 类型引用不明确。至少有两个名称空间(“System.Windows”和“System.Windows”)中已出现名为“VisualStateManager”的类型。请考虑调整程序集 XmlnsDefinition 特性。

    wpf中类型引用不明确.至少有两个名称空间(“System.Windows”和“System.Windows”)中已出现名为“VisualState 你是不是用了WPFToolKit?如果是的,那原因 ...

  7. 一个范围的两个数进行数位的累加,实现对两个数num1和num2的数位和相加

    对一个范围的两个数进行数位的累加,例如有两个数 15,19则 他们的数位和应该为: 1+5+1+6+1+7+1+8+1+9,结果为40. 测试说明 样例1 输入:1519 输出: 40 以下是不同方法 ...

  8. 合并两个数组并去重(ES5和ES6两种方式实现)

    合并两个数组并去重(ES5和ES6两种方式实现) ES6实现方式 let arr1 = [1, 1, 2, 3, 6, 9, 5, 5, 4] let arr2 = [1, 2, 5, 4, 9, 7 ...

  9. hdu5795 A Simple Nim 求nim求法,打表找sg值规律 给定n堆石子,每堆有若干石子,两个人轮流操作,每次操作可以选择任意一堆取走任意个石子(不可以为空) 或者选择一堆,把它分成三堆,每堆不为空。求先手必胜,还是后手必胜。

    /** 题目:A Simple Nim 链接:http://acm.hdu.edu.cn/showproblem.php?pid=5795 题意:给定n堆石子,每堆有若干石子,两个人轮流操作,每次操作 ...

  10. 刷题之给定一个整数数组 nums 和一个目标值 taget,请你在该数组中找出和为目标值的那 两个 整数

    今天下午,看了一会github,想刷个题呢,就翻出来了刷点题提高自己的实际中的解决问题的能力,在面试的过程中,我们发现,其实很多时候,面试官 给我们的题,其实也是有一定的随机性的,所以我们要多刷更多的 ...

随机推荐

  1. C语言基础题 22年5月

    (十六进制 %x  20.0f是%f  long 是%ld  unsigned int %#o  ) 编程题: 整数浮点数的上溢下溢 strcpy函数代码 int search(char *s, ch ...

  2. 如何用猿大师播放器在网页上同时播放20路以上海康威视高分辨率(1920*1080)摄像头RTSP视频流?

    问: 同时播放分辨率为1920*1080的高清分辨率的摄像头视频流,找了很长时间试过无数方法均不能满足,服务器转码方案卡顿非常严重,几乎不能播放.了解到猿大师可以用到本机的硬件解码和加速,播放高清视频 ...

  3. PointGNN未修改之前的结果 ---行人,骑行者

    dl 18 23

  4. 实验五:开源控制器实践——POX

    基本要求 1.tcpdump 验证Hub模块 h1 ping h2的tcpdump抓包结果截图 h1 ping h3的tcpdump抓包结果截图 2.tcpdump 验证Switch模块 h1 pin ...

  5. Windows软件堆栈溢出(stack overflow)的一些解决方法

    欢迎访问我的个人博客:xie-kang.com 原文地址 Windows平台下,有三种方法调整堆栈大小(适用于MSVC编译器): 1)添加编译参数:/F size  #其中size的单位是byte可设 ...

  6. SpringBoot解决跨域方案

    SpringBoot解决跨域的几种方式 跨域资源共享(CORS):通过修改Http协议header的方式,实现跨域.说的简单点就是,通过设置HTTP的响应头信息,告知浏览器哪些情况在不符合同源策略的条 ...

  7. 对Android关联SDK后,还是无法显示那俩图标的解决

    显示出来!!!! 可以这么解决: 步骤一: 步骤二: 找到这个,在上方的栏里面: 步骤三: 将这四个选中: 步骤四: 然后选中这个栏: 步骤五: 选中Android: 步骤六: 最后,点击右下角的Ap ...

  8. [Elixir/Erlang/Racket] 模式匹配,字符串,哈希表,格式化输出

    https://leetcode.cn/problems/evaluate-the-bracket-pairs-of-a-string/solutions/2057593/s-by-yhm138_-n ...

  9. python爬取今日的bing壁纸

    #!/usr/bin/python #你要的文件夹是 E://pics// ps:没有的话帮你建一个 import requests import os from datetime import da ...

  10. 2023GDKOI总结

    2023GDKOI总结 说明:不是GD选手,只是因为来zsjz集训就顺便参加了GDKOI,不过也不参与GD选手排名. 考前看了看GDKOI2021的题,当时是考了3天,每天4题,而里面只有一道题是我一 ...