当前位置:首页 > 洛谷 > 洛谷P6686题解题报告:基于频率统计与二分优化的等腰三角形组合计数算法解析

洛谷P6686题解题报告:基于频率统计与二分优化的等腰三角形组合计数算法解析

1天前

洛谷P6686题解题报告:基于频率统计与二分优化的等腰三角形组合计数算法解析 洛谷题解 等腰三角形 频率统计 二分查找 组合数学 第1张

一、题目解读

洛谷P6686题要求从给定的n个木棍长度中,计算可以组成多少种不同的等腰三角形。等腰三角形的特征为存在两条边长度相等,题目需考虑所有可能的组合情况,并处理重复计数问题。数据范围较大,需高效算法解决。

二、解题思路

采用以下核心思路:

1. 频率统计:使用哈希表(unordered_map)记录每个木棍长度的出现次数,快速获取频率信息。

2. 排序优化:对木棍长度数组排序,便于后续二分查找确定合法第三边范围。

3. 分类讨论:分两种情形处理:

    两边相等:遍历频率,若某长度出现次数≥2,则第三边需小于2倍该长度。通过二分查找确定符合条件的第三边数量,结合组合数计算方案数。

    三边相等:若某长度出现次数≥3,直接计算组合数C(n,3)。

4. 模运算:使用MOD = 998244353防止整数溢出,确保结果正确性。

三、解题步骤

1. 输入与初始化

    读入木棍数量n及长度数组a。

    创建频率哈希表freq,遍历a统计各长度频数。

2. 预处理

    对a排序,为二分查找做准备。

3. 处理“两边相等”情况

    遍历freq,对于频数≥2的长度len:

        1计算第三边上限max_len = 2*len - 1。

        2二分查找a中不超过max_len的元素数量total。

        3排除自身频数(避免三边相同),计算组合数C(cnt,2) * total,累加至答案。

4. 处理“三边相等”情况

    遍历freq,对于频数≥3的长度,计算组合数C(cnt,3)并累加。

5. 输出结果:模运算后的最终答案。

四、代码与注释

#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_map>
using namespace std;

const int MOD = 998244353; // 模数,防止溢出

int main() {
    int n;
    cin >> n;
    vector<int> a(n);
    unordered_map<int, int> freq; // 记录每个长度出现的频率

    for (int i = 0; i < n; ++i) {
        cin >> a[i];
        freq[a[i]]++; // 统计频数
    }

    sort(a.begin(), a.end()); // 排序便于二分查找

    long long ans = 0; // 答案初始化

    // 处理两条边相等的情况
    for (auto it = freq.begin(); it!= freq.end(); ++it) {
        int len = it->first; // 当前长度
        int cnt = it->second; // 频数

        if (cnt >= 2) { // 至少需要两根
            int max_len = 2 * len - 1; // 第三边上限(避免重复)
            auto upper = upper_bound(a.begin(), a.end(), max_len); // 二分查找上界
            int total = upper - a.begin(); // 符合条件的数量
            total -= cnt; // 减去自身频数(排除三边相等)
            long long combinations = (long long)cnt * (cnt - 1) / 2 % MOD; // 组合数C(cnt,2)
            ans = (ans + combinations * total % MOD) % MOD; // 累加结果
        }
    }

    // 处理三根边都相等的情况(等边三角形)
    for (auto it = freq.begin(); it!= freq.end(); ++it) {
        int cnt = it->second;
        if (cnt >= 3) {
            long long combinations = (long long)cnt * (cnt - 1) * (cnt - 2) / 6 % MOD; // C(cnt,3)
            ans = (ans + combinations) % MOD;
        }
    }

    cout << ans << endl;
    return 0;
}

五、总结

本算法通过频率统计与二分查找实现高效组合计数,核心在于:

1. 时间复杂度优化:排序+二分将第三边查找复杂度降至O(logn),避免暴力枚举

2. 组合数学应用:区分“两边相等”与“三边相等”场景,精确计算不重复方案。

3. MOD处理:保障大数运算正确性,符合题目要求。

该思路为同类组合计数问题提供了可复用的模板,尤其在数据规模较大时效果显著。


原创内容 转载请注明出处

分享给朋友:

相关文章

洛谷2181题解析:组合数学中顶点交点的计算与代码优化

洛谷2181题解析:组合数学中顶点交点的计算与代码优化

一、题目解读洛谷2181题要求计算n个顶点中任意选择4个顶点确定的交点数量。题目核心在于组合数学的应用,需通过排列组合公式推导结果,同时注意处理大数以避免溢出问题。理解题目中的“交点”定义(由4个顶点...

牛客23458题解析:基于二分查找的动态规划解法与代码实现

牛客23458题解析:基于二分查找的动态规划解法与代码实现

一、题目解读牛客23458题要求将给定的整数数组划分为m个连续子数组,使得每个子数组的和不超过某个最大值,且该最大值尽可能小。题目本质是求解“最小化最大值”的优化问题,需要结合二分查找与动态规划思想,...

洛谷1656题解:基于Tarjan算法求解割边问题(附代码与详细步骤)

洛谷1656题解:基于Tarjan算法求解割边问题(附代码与详细步骤)

一、题目解读洛谷1656题要求在无向图中找出所有割边(即删除后导致图不连通的边)。题目核心在于判断图的连通性,并识别哪些边是“桥”。需理解图论中的连通分量概念,以及如何通过算法高效定位割边。二、解题思...

洛谷2652题解析:同花顺排序问题的动态规划与滑动窗口优化

洛谷2652题解析:同花顺排序问题的动态规划与滑动窗口优化

一、题目解读洛谷2652题要求对一组扑克牌进行排序,目标是找到最少需要调整的次数,使得所有牌形成同花顺。题目中,扑克牌由花色和数字组成,需先按花色排序,再在同花色内按数字排序。核心难点在于如何处理花色...

洛谷P3393题解:基于多源BFS与Dijkstra算法求解图论最小花费路径问题

洛谷P3393题解:基于多源BFS与Dijkstra算法求解图论最小花费路径问题

一、题目解读洛谷P3393题要求在一个包含N个城市和M条双向道路的图中,求解从起点1到终点N的最小花费路径。图中存在僵尸城市(僵尸无法通过)和危险城市(由僵尸城市扩散S步后标记),需要避开所有危险城市...

洛谷P2789题解:递归算法与避免重复计算的技巧

洛谷P2789题解:递归算法与避免重复计算的技巧

一、题目解读洛谷P2789题要求计算n条直线在平面上两两相交产生的交点总数。题目强调交点不重复,需考虑平行线情况。关键点在于如何高效枚举所有可能的交点组合,并排除重复结果。二、解题思路采用递归算法,核...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。