2023-03-25:若两个正整数的和为素数,则这两个正整数称之为“素数伴侣“。 给定N(偶数)个正整数中挑选出若干对,组成“素数伴侣“, 例如有4个正整数:2,5,6,13, 如果将5和6分为一组的
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分为一组的的更多相关文章
- [2019.03.25]Linux中的查找
TMUX天下第一 全世界所有用CLI Linux的人都应该用TMUX,我爱它! ======================== 以下是正文 ======================== Linu ...
- Java基础-多线程编程-1.随便选择两个城市作为预选旅游目标。实现两个独立的线程分别显示10次城市名,每次显示后休眠一段随机时间(1000ms以内),哪个先显示完毕,就决定去哪个城市。分别用Runnable接口和Thread类实现。
1.随便选择两个城市作为预选旅游目标.实现两个独立的线程分别显示10次城市名,每次显示后休眠一段随机时间(1000ms以内),哪个先显示完毕,就决定去哪个城市.分别用Runnable接口和Thread ...
- @有两个含义:1,在参数里,以表明该变量为伪参数 ,在本例中下文里将用@name变量代入当前代码中2,在字串中,@的意思就是后面的字串以它原本的含义显示,如果不
@有两个含义:1,在参数里,以表明该变量为伪参数 ,在本例中下文里将用@name变量代入当前代码中 2,在字串中,@的意思就是后面的字串以它原本的含义显示,如果不加@那么需要用一些转义符\来显示一些特 ...
- 有两个指针pa,pb分别指向有两个数,a,b,请写一个函数交换两个指针的指向,也就是让pa指向b,让pb指向a
题目:有两个指针pa,pb分别指向有两个数,a,b,请写一个函数交换两个指针的指向,也就是让pa指向b,让pb指向a,具体实现如下: #include<stdlib.h> #include ...
- 如何从两个List中筛选出相同的值
问题 现有社保卡和身份证若干,想要匹配筛选出一一对应的社保卡和身份证. 转换为List socialList,和List idList,从二者中找出匹配的社保卡. 模型 创建社保卡类 /** * @a ...
- 在编写wpf界面时候中出现如下错误: 类型引用不明确。至少有两个名称空间(“System.Windows”和“System.Windows”)中已出现名为“VisualStateManager”的类型。请考虑调整程序集 XmlnsDefinition 特性。
wpf中类型引用不明确.至少有两个名称空间(“System.Windows”和“System.Windows”)中已出现名为“VisualState 你是不是用了WPFToolKit?如果是的,那原因 ...
- 一个范围的两个数进行数位的累加,实现对两个数num1和num2的数位和相加
对一个范围的两个数进行数位的累加,例如有两个数 15,19则 他们的数位和应该为: 1+5+1+6+1+7+1+8+1+9,结果为40. 测试说明 样例1 输入:1519 输出: 40 以下是不同方法 ...
- 合并两个数组并去重(ES5和ES6两种方式实现)
合并两个数组并去重(ES5和ES6两种方式实现) ES6实现方式 let arr1 = [1, 1, 2, 3, 6, 9, 5, 5, 4] let arr2 = [1, 2, 5, 4, 9, 7 ...
- hdu5795 A Simple Nim 求nim求法,打表找sg值规律 给定n堆石子,每堆有若干石子,两个人轮流操作,每次操作可以选择任意一堆取走任意个石子(不可以为空) 或者选择一堆,把它分成三堆,每堆不为空。求先手必胜,还是后手必胜。
/** 题目:A Simple Nim 链接:http://acm.hdu.edu.cn/showproblem.php?pid=5795 题意:给定n堆石子,每堆有若干石子,两个人轮流操作,每次操作 ...
- 刷题之给定一个整数数组 nums 和一个目标值 taget,请你在该数组中找出和为目标值的那 两个 整数
今天下午,看了一会github,想刷个题呢,就翻出来了刷点题提高自己的实际中的解决问题的能力,在面试的过程中,我们发现,其实很多时候,面试官 给我们的题,其实也是有一定的随机性的,所以我们要多刷更多的 ...
随机推荐
- zabbix 告警说明及触发cpu告警
1. https://www.cnblogs.com/caonw/p/12766454.html 1.内存检测:Template OS Linux:vm.memory.size[available]. ...
- Linux挂载SMB共享文件夹
mount -t cifs -o username=xxxx,password=xxxx //PATH/TO/Shared/Folder /mount/point
- NDVI最大值合成
这里有NDVI250m分辨率的数据,目标:合成年最大值数据 [Spatial Analyst工具]|[局部分析]|[像元统计数据]
- ASP.NET Core - 配置系统之自定义配置提供程序
4. 自定义配置提供程序 在 .NET Core 配置系统中封装一个配置提供程序关键在于提供相应的 IconfigurationSource 实现和 IConfigurationProvider 接口 ...
- iText5实现Java生成PDF
参考代码:https://github.com/youcong1996/study_simple_demo 参考博客:https://blog.csdn.net/weixin_37848710/art ...
- volatile 关键字(轻量级同步机制)
更多内容,前往IT-BLOG volatile 表示 "不稳定" 的意思.用于修饰共享可变变量,即没有使用 final(不可变变量) 关键字修饰的实例变量或静态变量,相应的变量就被 ...
- 可靠消息最终一致性【本地消息表、RocketMQ 事务消息方案】
更多内容,前往IT-BLOG 一.可靠消息最终一致性事务概述 可靠消息最终一致性方案是指当事务发起方执行完成本地事务后并发出一条消息,事务参与方(消息消费者)一定能够接收消息并处理事务成功,此方案强调 ...
- 简单部署halo博客
第一步,购买服务器,安装宝塔linux面板. 第二步,在宝塔linux面板的软件商店安装docker管理器 第三步,配置阿里云镜像加速 修改镜像加速 vim /etc/docker/daemon.js ...
- Kubernetes(k8s)实现IPv4/IPv6网络双栈
背景 如今IPv4IP地址已经使用完毕,未来全球会以IPv6地址为中心,会大力发展IPv6网络环境,由于IPv6可以实现给任何一个设备分配到公网IP,所以资源是非常丰富的. 配置hosts [root ...
- Atcoder Regular Contest 093 C - Bichrome Spanning Tree
给定一张图,对图上边黑白染色,使得同时选择了两种颜色边的最小生成树边权和为X,求染色方案数. 先求出图的\(mst\)大小,然后分三类讨论: 1.\(X<mst\) 无解 2.\(X==mst\ ...