【组合数学 放球问题 虚拟点 小于等于转小于】1621. 大小为 K 的不重叠线段的数目

本文涉及知识点

放球问题
组合数学汇总
本题难道分:2198

LeetCode1621. 大小为 K 的不重叠线段的数目

给你一维空间的 n 个点,其中第 i 个点(编号从 0 到 n-1)位于 x = i 处,请你找到 恰好 k 个不重叠 线段且每个线段至少覆盖两个点的方案数。线段的两个端点必须都是 整数坐标 。这 k 个线段不需要全部覆盖全部 n 个点,且它们的端点 可以 重合。
请你返回 k 个不重叠线段的方案数。由于答案可能很大,请将结果对 109 + 7 取余 后返回。
示例 1:
在这里插入图片描述
输入:n = 4, k = 2
输出:5
解释:
如图所示,两个线段分别用红色和蓝色标出。
上图展示了 5 种不同的方案 {(0,2),(2,3)},{(0,1),(1,3)},{(0,1),(2,3)},{(1,2),(2,3)},{(0,1),(1,2)} 。
示例 2:

输入:n = 3, k = 1
输出:3
解释:总共有 3 种不同的方案 {(0,1)}, {(0,2)}, {(1,2)} 。
示例 3:

输入:n = 30, k = 7
输出:796297179
解释:画 7 条线段的总方案数为 3796297200 种。将这个数对 109 + 7 取余得到 796297179 。
示例 4:

输入:n = 5, k = 3
输出:7
示例 5:

输入:n = 3, k = 2
输出:1

提示:

2 <= n <= 1000
1 <= k <= n-1

放球问题(错误解法)

二个盒子:
(0,2),(2,3) 两个盒子,第一个盒子2个球,第二个盒子1个球。
(0,1),(1,3)两个盒子,第一个盒子1个球,第二个盒子2个球。
三个盒子:
三个盒子,每个盒子一个球,然后仍掉一个盒子。
(0,1),(1,3) 扔掉第二个盒子。
(1,2),(2,3) 扔掉第一个盒子。
(0,1),(1,2)扔掉第三个盒子。
球完全相同,因为第一个盒子只能是:{0,1 … \dots }
盒子不同,二个盒子的两个情况,分别是{2,1}和{1,2}。
盒子不能为空。

从k到n-1枚举i,将n-1个球放到i个盒子中,然后乘以C i i − k _i^{i-k} iik ,表示扔掉i-k个盒子。
f(i) = C n − 2 i − 1 _{n-2}^{i-1} n2i1 × \times × C i i − k _i^{i-k} iik
ret = ∑ i : k n − 1 \sum_{i:k}^{n-1} i:kn1f(i)

i个盒子 和i+1 个盒子,前者扔掉一个盒子,后者扔掉2个盒子后,可能和前者重复。如:
{1,1,2} {1,1,1,1} 扔掉2和{1,1}后,为{1,1}。

组合数学

本题    ⟺    \iff 0 <= l1 < r1 <=l2 < r2 ⋯ \cdots lk < rk < n (l1,r1 ⋯ \cdots lk,rk)的组合数。
令 lli = li+i rri = ri+i , (li,ri)和(lli,rri)一一对应,故数量相等。
1 <= ll1 < rr1 < ll2 < rr2 ⋯ \cdots llk < rrk < n+k    ⟺    \iff 从[1,n+k-1)中寻找2k 个不同的数。
即:C n + k − 1 2 k _{n+k-1}^{2k} n+k12k

核心代码

template<int MOD = 1000000007>
class C1097Int
{
public:
	C1097Int(long long llData = 0) :m_iData(llData% MOD)
	{

	}
	C1097Int  operator+(const C1097Int& o)const
	{
		return C1097Int(((long long)m_iData + o.m_iData) % MOD);
	}
	C1097Int& operator+=(const C1097Int& o)
	{
		m_iData = ((long long)m_iData + o.m_iData) % MOD;
		return *this;
	}
	C1097Int& operator-=(const C1097Int& o)
	{
		m_iData = (m_iData + MOD - o.m_iData) % MOD;
		return *this;
	}
	C1097Int  operator-(const C1097Int& o)
	{
		return C1097Int((m_iData + MOD - o.m_iData) % MOD);
	}
	C1097Int  operator*(const C1097Int& o)const
	{
		return((long long)m_iData * o.m_iData) % MOD;
	}
	C1097Int& operator*=(const C1097Int& o)
	{
		m_iData = ((long long)m_iData * o.m_iData) % MOD;
		return *this;
	}
	C1097Int  operator/(const C1097Int& o)const
	{
		return *this * o.PowNegative1();
	}
	C1097Int& operator/=(const C1097Int& o)
	{
		*this /= o.PowNegative1();
		return *this;
	}
	bool operator==(const C1097Int& o)const
	{
		return m_iData == o.m_iData;
	}
	bool operator<(const C1097Int& o)const
	{
		return m_iData < o.m_iData;
	}
	C1097Int pow(long long n)const
	{
		C1097Int iRet = 1, iCur = *this;
		while (n)
		{
			if (n & 1)
			{
				iRet *= iCur;
			}
			iCur *= iCur;
			n >>= 1;
		}
		return iRet;
	}
	C1097Int PowNegative1()const
	{
		return pow(MOD - 2);
	}
	int ToInt()const
	{
		return m_iData;
	}
private:
	int m_iData = 0;;
};

template<class Result = C1097Int<> >
class CCombination
{
public:
	CCombination()
	{
		m_v.assign(1, vector<Result>(1,1));
	}
	Result Get(int sel, int total)
	{
		assert(sel <= total);
		while (m_v.size() <= total)
		{
			int iSize = m_v.size();
			m_v.emplace_back(iSize + 1, 1);
			for (int i = 1; i < iSize; i++)
			{
				m_v[iSize][i] = m_v[iSize - 1][i] + m_v[iSize - 1][i - 1];
			}
		}
		return m_v[total][sel];
	}
protected:
	vector<vector<Result>> m_v;
};

class Solution {
public:
	int numberOfSets(int n, int k) {
		
		CCombination com;
        C1097Int<> biRet = com.Get(2*k,n+k-1);
		return biRet.ToInt();
	}
};

测试用例

template<class T>
void Assert( vector<T> v1,  vector<T> v2)
{
	if (v1.size() != v2.size())
	{
		assert(false);
		return;
	}
	for (int i = 0; i < v1.size(); i++)
	{
		assert(v1[i] == v2[i]);
	}
}

template<class T>
void Assert(const T& t1, const T& t2)
{
	assert(t1 == t2);
}

int main()
{	
	int k;
	{
		Solution slu;
		auto res = slu.numberOfSets(30, 27);
		Assert(res, 1540);
	}
	{
		Solution slu;
		auto res = slu.numberOfSets(4,2);
		Assert(res, 5);
	}
	{
		Solution slu;
		auto res = slu.numberOfSets(3,1);
		Assert(res, 3);
	}
	
	{
		Solution slu;
		auto res = slu.numberOfSets(5, 3);
		Assert(res, 7);
	}
	{
		Solution slu;
		auto res = slu.numberOfSets(3, 2);
		Assert(res, 1);
	}
	{
		Solution slu;
		auto res = slu.numberOfSets(30, 7);
		Assert(res, 796297179);
	}
}

组合数学+ 虚拟点

如果起点和终点不重合,则 C n 2 k _{n}^{2k} n2k
假定有i1个重合点,那一定有2n-i1个非重合点,i1 ∈ \in [0,k-1] 第一条线段 的起点不会是重合点。
从n个真实点和k-1个虚拟点,共n+K-1个点中选取2k个点。一定对应一个合法方案,且不会重复。

至少存在一个方案

将选择真实点排序后放到队列中,is[i] 表示第i个虚拟节点是否选取。
队列中的前两个节点是第一条线段,队列出队两个元素。
for( i = 0 to k-1)
{ 新线段 = ( 前一个线段的终点 , 队首 ) , 出队 i s [ i ] 新线段 = 队伍的前两个元素 , 出队两个元素 e l s e \begin{cases} 新线段=(前一个线段的终点,队首),出队 && is[i] \\ 新线段=队伍的前两个元素 ,出队两个元素 && else \\ \end{cases} {新线段=(前一个线段的终点,队首),出队新线段=队伍的前两个元素,出队两个元素is[i]else
总共2k个点,每次处理2次,k次刚好处理完。
虚拟节点只有有,才处理。所以不会不足。最多k-1个,处理k-1次。所以不会剩余。
节点一定处理完,虚拟处没有不足或剩余,故真实节点也没不足或处理完。

不会有其它对应方案

按语义操作是唯一的,故不存在其它方案。

方案数不重复

一,虚拟节点数不同,则一定不同。
二,虚拟节点数量相同,但至少某个虚拟节点不同。虚拟节点排序后,令两个方案最小不同节点分别为i1,i2。i3 = min(i1,i2)。
{ 两方案不同 ( i 3 − 1 ) 的终点不同。 第 i 3 条线段的起点一定不同 o t h e r \begin{cases} 两方案不同 && (i3-1)的终点不同。 \\ 第i3条线段的起点一定不同 && other \\ \end{cases} {两方案不同i3条线段的起点一定不同(i31)的终点不同。other
三,虚拟节点完全相同,真实节点不同。
真实节点排序后,令最小不同的节点分别为i1,i2。不失一般性。令这两个节点都是第i3条线段的起点。则第i3条线段起点不同。

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771

如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

相关下载

想高屋建瓴的学习算法,请下载《喜缺全书算法册》doc版
https://download.csdn.net/download/he_zhidan/88348653

我想对大家说的话
《喜缺全书算法册》以原理、正确性证明、总结为主。
闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/653732.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

菊花链通信技术整理

目录 一、菊花链简介 二、菊花链与CAN通信的区别 三、常见的菊花链AFE芯片 四、菊花链数据结构 五、菊花链方案介绍 一、菊花链简介 首先简单的说一下菊花链以及菊花链的应用&#xff0c;在目前国内的BMS开发中&#xff0c;我们应用最广泛的目前还还是分布式&#xff0c;…

代码随想录算法训练营第七天| 454.四数相加II 、383. 赎金信、 15. 三数之和、18. 四数之和

454.四数相加II 题目链接&#xff1a; 454.四数相加II 文档讲解&#xff1a;代码随想录 状态&#xff1a;没做出来&#xff0c;没想到考虑重复的情况&#xff01; 题解&#xff1a; public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {// 结果计数…

java的变量关系~使用和扩展

一、变量的概述 1、什么是变量 白话:变量就是一个装东西的盒子。 通俗:变量是用于存放数据的容器。我们通过变量名 获取数据&#xff0c;甚至数据可以修改。 2、变量在内存中的存储 本质:变量是程序在内存中申请的一块用来存放数据的空间&#xff0c;类似我们酒店的房间&a…

基于多源数据的微服务系统失败测试用例诊断

简介 本文介绍由南开大学、华为云及清华大学共同合作的论文:基于多源数据的微服务系统失败测试用例诊断。该论文已被FSE 2024&#xff08;The ACM International Conference on the Foundations of Software Engineering&#xff09; 会议录用&#xff0c;论文标题为: Fault D…

JS中的数组很重要,怎样定义(声明)

为什么呢&#xff1f;在java中有集合&#xff0c;数组的作用就弱了&#xff0c;其高光时刻基本都被集合代替了。在JS中没有集合&#xff0c;数组就有点忙不过来了。你说它重要不重要&#xff1f;&#xff01; 在JS中&#xff0c;怎样定义一个数组呢&#xff1f; 数组的声明方…

动手学操作系统(二、编写MBR主引导记录)

动手学操作系统&#xff08;二、编写MBR主引导记录&#xff09; 文章目录 动手学操作系统&#xff08;二、编写MBR主引导记录&#xff09;1. 实模式和保护模式2. BIOS与MBR3. MBR程序Reference 在之前的学习内容中&#xff0c;我们已经实现了基本的仿真环境bochs的搭建&#xf…

【Linux】数据链路层协议+ICMP协议+NAT技术

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;折纸花满衣 &#x1f3e0;个人专栏&#xff1a;Linux 目录 &#x1f449;&#x1f3fb;数据链路层&#x1f449;&#x1f3fb;以太网以太网帧格式网卡Mac地址对比ip地址 &#x1f449;&#x1f3fb;MTUMTU…

员工管理和激励怎么做?试试场景化激励解决方案!

截止到2020年底&#xff0c;中国企业主体数量达3858.3万&#xff0c;同比增速达11.1%。如何留住人才、激励人才以强化人才与企业“黏性”&#xff0c;最大化提升员工的忠诚度与敬业度&#xff0c;成为企业未来人才发展战略的主要方向之一。 一、传统激励方式存在哪些不足 传统的…

【NumPy】权威指南:使用NumPy的percentile函数进行百分位数计算

&#x1f9d1; 博主简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟&#xff0c;欢迎关注。提供嵌入式方向…

计算机找不到msvcr110.dll如何解决,总结5种简单靠谱的方法

在日常使用电脑的过程中&#xff0c;我们可能会遇到一些错误提示&#xff0c;其中之一就是“msvcr110.dll丢失”。这个错误通常会导致某些程序无法正常运行&#xff0c;为了解决这个问题&#xff0c;下面我将介绍5种有效的解决方法。 一&#xff0c;了解msvcr110.dll是什么 ms…

网络之再谈体系结构

大家都知道的是网络的体系结构&#xff0c;现代软件常用的体系结构无非是TCP/IP协议栈&#xff0c;OSI因为实现复杂并且效率没有TCP/IP协议栈好&#xff0c;所以不用OSI&#xff0c;但是&#xff0c;最近在复习网络知识的时候&#xff0c;发现了一些奇怪的地方&#xff0c;那就…

TinyEngine 低代码引擎:带你5分钟高效构建游戏登录界面

本文由体验技术团队 TinyEngine 项目成员李旭宏创作&#xff0c;欢迎大家实操体验&#xff0c;本体验项目基于 TinyEngine 低代码引擎提供的环境&#xff0c;通过体验简单拖、拉、拽的形式帮助开发者快速了解低代码引擎的使用流程&#xff0c;达到快速开发游戏登录界面的效果。…

yolox-何为混合精度计算AMP?

何为AMP&#xff1f; 全称&#xff1a;Automatic mixed precision自动混合精度。 功能&#xff1a;在神经网络推理过程中&#xff0c;实现针对不同层采用不同的数据精度进行计算&#xff0c;从而实现节省显存和加速训练的目的。 此处提到的不同数据精度包括&#xff1a;32位浮…

每日两题 / 131. 分割回文串 42. 接雨水(LeetCode热题100)

131. 分割回文串 - 力扣&#xff08;LeetCode&#xff09; 数据量较小&#xff0c;考虑直接暴力&#xff0c;每次dfs&#xff1a;以bg作为左区间&#xff0c;往右遍历&#xff0c;找到一段回文串区间后&#xff0c;将回文串插入vector<string>&#xff0c;并以下一个下标…

适合下班做的副业兼职、1天挣300,7天涨粉2万

最近小红书上有类视频火了&#xff01; 周周近财&#xff1a;让网络小白少花冤枉钱&#xff0c;赚取第一桶金 利用AI制作的漫画解说历史小说视频。视频以《明朝那些事儿》为蓝本&#xff0c;一上线就疯狂吸粉&#xff0c;多条视频内容都大爆了。 就是这个账号&#xff0c;仅仅…

POLARDB:新零售用户MySQL上云最佳选择

什么是云数据库POLARDB&#xff1f; POLARDB是阿里云自主研发的最新一代RDS关系型数据库&#xff0c;是特别针对互联网场景设计的Cloud-Native 云原生数据库。POLARDB for MySQL版本&#xff0c;在提供100%兼容MySQL5.6/8.0的关系型事务处理ACID特性之上&#xff0c;能够提供完…

MySQL:CRUD初阶(有图有实操)

文章目录 &#x1f4d1;1. 数据库的操作&#x1f324;️1.1 显示当前的数据库&#x1f324;️1.2 创建数据库&#x1f324;️1.3 选中数据库&#x1f324;️1.4 删除数据库 &#x1f4d1;2. 表的操作&#x1f324;️2.1 查看表结构&#x1f324;️2.2 创建表&#x1f324;️2.3…

实战指南:Vue 2基座 + Vue 3 + Vite + TypeScript微前端架构实现动态菜单与登录共享

实战指南&#xff1a;Vue 2基座 Vue 3 Vite TypeScript子应用vue2微前端架构实现动态菜单与登录共享 导读&#xff1a; 在当今的前端开发中&#xff0c;微前端架构已经成为了一种流行的架构模式。本文将介绍如何结合Vue 2基座、Vue 3子应用、Vite构建工具和TypeScript语言…

【IC】partial good

假设单core良率80%&#xff0c;core pass 数量分布呈二项分布。 16个core全pass的概率为&#xff1a; 有n个core pass的概率为&#xff1a; 分布如下&#xff1a; 当np>5且nq>5时&#xff0c;二项分布近似服从正态分布

Python魔法之旅-魔法方法(01)

目录 一、概述 1、定义 2、作用 二、主要应用场景 1、构造和析构 2、操作符重载 3、字符串和表示 4、容器管理 5、可调用对象 6、上下文管理 7、属性访问和描述符 8、迭代器和生成器 9、数值类型 10、复制和序列化 11、自定义元类行为 12、自定义类行为 13、类…