1 条题解
-
0
解法思路
1. 统计相同花瓣数的花朵数量
首先将数组排序,然后统计每个花瓣数 的出现次数,记作 。
同时,因为总花费不能超过 ,所以对于一种花瓣数 ,最多只能选取 朵(否则总花瓣数会超过 ),但实际数量受 限制,因此实际可选数量为 。2. 枚举相邻花瓣数的组合
由于任意两朵花的花瓣数之差不超过 ,所以选出的花束只可能包含两种相邻的花瓣数 和 (也可能只包含一种)。
我们可以遍历所有可能的花瓣数 ,并枚举选取 的数量 ()。
此时已花费 硬币,剩余硬币数为 。对于花瓣数 ,最多可以选取
$$k_2 = \min\left(c_{x+1},\ \left\lfloor \frac{m - k_1 \cdot x}{x+1} \right\rfloor\right) $$朵。
则该组合的总花瓣数为 。
对所有 和所有可能的 取最大值即可。3. 为什么枚举 的复杂度是 ?
对于每个 , 从 枚举到 。
- 如果 ,则枚举次数为 。
- 如果 ,则枚举次数为 ,此时因为 很大, 很小,总和仍然受限于 和不同 的个数。
事实上,所有 的 之和不超过 ,而不同 的个数也 ,因此总枚举次数为 。
排序的复杂度为 ,因此总复杂度为 ,满足题目要求(所有测试用例的 之和不超过 )。
4. 边界处理
- 当没有 的花朵时,,此时 ,相当于只选花瓣数为 的花。
- 当 时,相当于只选花瓣数为 的花。
- 注意 可能非常大(),但 最小为 ,故 在计算时需要用 64 位整数。
算法步骤
- 读入 组测试用例。
- 对每个测试用例:
- 读入 和数组 。
- 对 排序。
- 统计每个不同花瓣数 及其出现次数 ,存储到列表
pairs中(例如 )。 - 初始化答案 。
- 遍历每个 (注意同时要能访问 ,可以再存储一个映射或直接按顺序处理):
- 设当前花瓣数为 ,数量为 ;下一个花瓣数为 ,数量为 (若不存在则 )。
- 计算 。
- 对于 到 :
- 剩余硬币 。
- 若 则跳出。
- 。
- 更新 。
- 输出 。
示例验证
以第一个测试用例为例:
,花朵花瓣:
排序后得到: 出现 次, 出现 次, 出现 次。-
枚举 :,,
- :,,总花瓣
- :,,总花瓣
- :,,总花瓣
-
枚举 :,,
- :,,总花瓣
- :,,总花瓣
- :,,总花瓣
-
枚举 :,,
- :,(无 ),总花瓣
- :,,总花瓣
最大值为 ,与样例输出一致。
完整题解代码框架(C++ 风格)
#include <bits/stdc++.h> using namespace std; int main() { int t; cin >> t; while (t--) { int n; cin >> n; vector<int> a(n); bool hasZero = false; int negCount = 0; for (int i = 0; i < n; i++) { cin >> a[i]; if (a[i] == 0) hasZero = true; else if (a[i] < 0) negCount++; } // 乘积为负:奇数个负数且无0 if (!hasZero && negCount % 2 == 1) { cout << "0\n"; } // 乘积为0 else if (hasZero) { cout << "0\n"; } // 乘积为正 else { cout << "1\n"; // 输出任意一个元素改成0 cout << "1 0\n"; } } return 0; }复杂度分析
- 排序:
- 统计和枚举:(因为每个花朵最多被作为 枚举一次)
- 总复杂度:,满足题目限制。
- 1
信息
- ID
- 7234
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 2
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者