20260401 刷了一堆算法题
完美对计数问题
有 个物品,每个物品有 个属性。第 件物品的第 个属性用一个正整数表示,记为 。
两个不同的物品 被称为完美对,当且仅当满足以下条件:
问题: 求完美对的总个数。
解
则有:
因此我们定义补全序列:
差分序列:
对每个物品,我们求它的补全序列,在哈希表里找该序列出现的次数并累加,然后把它的差分序列计数+1,哈希表用map<vector<int>, int>实现
2. 选择物品
题目描述 有 个物品可供选择,必须从中选择 个物品。请按字典序顺序输出所有选取方案的物品编号。
注意事项
- 组合去重:例如 、 与 被认为是同一种方案。
- 格式要求:仅输出每种方案中字典序最小的排列(如
1 2 3)。
数据范围
复杂度要求
- 时间复杂度:
- 空间复杂度:
解
简单的组合数问题,我们用递归combine(int n, int m, int start, vector<int>& a)解决问题:
| |
4. 比例问题
题目描述 小强想要从区间 中选出一个整数 ,从区间 中选出一个整数 。
在满足以下比例条件的前提下,寻找使 和 的乘积最大的数值对:
输入要求
- 如果存在满足条件的 和 ,输出使得 最大的那一组结果。
- 如果不存在这样的 和 ,请输出
0 0。
解
我们首先通过gcd对 进行化简:
接着,对x和y的等式,我们引入一个 来表示:
那么, 就变成了 ,由于此时 和 是常数,由此我们的问题就转变成了找最大的 。 的上下限我们观察x和y的区间得到:
由于我们只关心上界,因此我们的问题变成了: 是否能找到一个整数 ,满足 如果找不到,我们就说无解,如果找到了,就按照上面的公式求解x和y
5. 小强修水渠
题目描述 在一张 2D 地图上,小强拥有 座房子。由于地理位置限制,无法直接为每座房子提供水源。因此,小强打算修建一条无限长且平行于 轴的水渠。
这条水渠可以看作是一条直线 。现在小强需要确定水渠的具体位置(即确定 的值),使得这 座房子到水渠的垂直距离之和最小。
输出要求 输出计算得到的最小距离总和。
由于水渠平行于y轴,因此y坐标与水渠距离无关,我们不用考虑,那么此时问题变成了:
其中 为水渠坐标。 首先一眼看出水渠如果在所有房子的左边or右边都不是最优解,那么在中间应该如何取舍呢?我们找几个简单的例子看看:
房子总共有偶数个(例如,就是2 or 4个,没关系) 此时水渠如果在正中间,无论怎么移动,都不影响最终结果(你可以将上面的式子按左侧右侧展开绝对值看看,最终 会被抵消)
房子总共有奇数个(例如,3个) 此时水渠必须在中位数的位置上,因为假设我们把这个中位数去掉,就变成偶数个的情况,此时水渠在中间怎么移动都行,但是加入中位数以后为了将这个距离对答案的贡献降到最小(也就是0),我们把水渠建在这个位置最合适。
在C++中,有一个很好的函数可以解决这件事:
nth_element(a.begin(), a.begin() +mid, a.end())
可以将整个数组的中位数放在mid的位置上。
6. 国际交流会
题目描述 小强主办了一场国际交流会,所有参会人员围坐在一张圆桌旁。为了让不同国家的人充分感受异域气息,小强希望最大化邻座两人之间的差异程度之和。
已知每两人之间都存在一个衡量“差异程度”的数值,请你为他安排座位次序,使得圆桌上相邻两人差异程度的总和达到最大。
注意事项
- 这是一个环形排列问题,首尾两人也属于相邻关系。
- 目标是求得一个排列,使得 最大。
解
没什么好说的,本来以为需要 建图然后跑最大生成树,但是最大生成树也可能是个星形结构无法成环,或者最大权哈密顿回路问题?它和旅行商问题正好相反,但是它们是NP-Hard问题,无法求解。 其实是想复杂了,这道题由于它只是数值大小的关系,没那么复杂。我们可以想象每个数字在数轴上是一个点,我们希望走过的步长最长,那么就每次从最右边走到最左边就可以了。 写成算法就是:
- 先排序
- 维护两个指针从两头双向往中间走(保证 ),然后把值交替写到新数组里
- 如果n为奇数,把中位数写到新数组的最后
- 计算新数组的前缀差和
7. 小强的神奇矩阵
题目描述 小强有一个大小为 的矩阵 。他计划从矩阵的每一列中各取出一个数字,按照原始列的顺序组成一个长度为 的新数组 。
即对于数组中的第 个元素 ,它可以是 中的任意一个。
问题 请问如何选择每列的数字,才能使得相邻元素之差的绝对值之和最小?即求以下表达式的最小值:
解
一个dp,只不过分了三个维度
每一列的三个数字都尝试和前一列的三个数字进行计算,然后维护 的最小值,最后从 里找最小值就行了。