You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求满足组合数C(n,k)≤x的最大n的高效计算优化方案

针对k=1/2/3的组合数逆问题优化方案

给定k∈{1,2,3}、x∈[0, C(n',k)](n'为已知常数如1000),要求快速找到满足C(n,k)≤x的最大n且n≤n'。针对原迭代方案最坏需n'-k次循环的问题,可利用k值极小的特性,直接通过数学公式计算近似解,再做1次验证调整,实现几乎无循环的高效求解:

分情况推导

k=1的情况

组合数C(n,1)=n,因此最大n直接取min((long long)x, n'),无需额外计算。

k=2的情况

由C(n,2)=n(n-1)/2 ≤x,整理得二次不等式:

n² -n -2x ≤0

通过求根公式得到正根:
n = (1 + sqrt(1 + 8*x)) / 2
取该值的整数部分floor(n),再与n'取最小值即可。若担心浮点精度误差,可额外判断下一个整数是否满足条件(实际因x范围限制,精度足够时无需此步骤)。

k=3的情况

由C(n,3)=n(n-1)(n-2)/6 ≤x,整理得三次不等式:

n³ -3n² +2n -6x ≤0

先通过立方根近似估算n的初始值:
n ≈ cbrt(6*x) + 1
取整数部分后,只需验证该值及相邻的1-2个整数(最多1次调整),即可得到满足条件的最大n,再与n'取最小值。

优化后的C++模板代码

#include <cmath>
#include <algorithm>

template<int k>
long long find_max_n(long long x, long long n_prime) {
    if (x < 0) return -1; // 非法输入处理
    switch(k) {
        case 1:
            return std::min(x, n_prime);
        case 2:
            if (x == 0) return 0; // C(0,2)=0,C(1,2)=0
            double sqrt_val = sqrt(1 + 8.0 * x);
            long long n = static_cast<long long>((1 + sqrt_val) / 2);
            // 仅需最多1次循环修正精度问题
            while (n*(n-1)/2 <= x) n++;
            n--;
            return std::min(n, n_prime);
        case 3:
            if (x == 0) return 0; // C(0,3)=C(1,3)=C(2,3)=0
            double cbrt_val = cbrt(6.0 * x);
            long long n = static_cast<long long>(cbrt_val) + 1;
            // 仅需最多1次循环修正近似值
            while ((n*(n-1)*(n-2))/6 <= x) n++;
            n--;
            return std::min(n, n_prime);
        default:
            return -1; // 仅支持k=1,2,3
    }
}

代码说明

  • 针对k=2和k=3的情况,仅需最多1次循环调整(初始近似值与真实解差距极小),远优于原最坏n'-k次循环的方案;
  • 利用数学公式直接估算,避免了迭代计算组合数的大量重复运算;
  • 加入边界情况处理(如x=0时的结果),保证鲁棒性。

内容的提问来源于stack exchange,提问作者PingFloyd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 13:45:26