求组合数的个数

本文探讨了使用1、2、5这三个数的不同个数组合来构成100的所有可能方式,并给出了两种不同的C#实现方案。第一种方案通过三层循环遍历所有可能的组合,第二种方案则进行了优化,减少了不必要的计算。

需求:求出用1、2、5这三个数的不同个数组合的和为100的组合个数。如100个1是一个组合,5个1加19个5是一个组合等等。

分析:很明显1、2、5本身这三个数无论怎么加都无法达到100,必须用多个1,多个2,多个5才能加到100;那么到底需要用多少个1,多少个2,多个5呢?

         我们设1、2、5 这三个数的个数分别为x、y、z 即x* 1 + y* 2 +z* 5=100 !

CSharp实现代码:

namespace DemoC
{
    class Program
    {
        //定义静态计算函数
        public static int CountC()
        {
            int number = 0;   //初始化计数器
            int x, y, z; 
            //设置循环条件
            for (x = 0; x <= 100; x++)
                for (y = 0; y <= 50; y++)
                    for (z = 0; z <= 20; z++)
                        if (x * 1 + y * 2 + z * 5 == 100)
                            number++;
            return number;
        }
        static void Main(string[] args)
        {
            int cNumber = CountC();
            Console.WriteLine("满足条件的组合个数为 {0}", cNumber);
            Console.ReadKey();
        }
    }
}

输出结果:541

上面的方法,CountC()函数一共要计算100*50*20次,效率非常低下;另一种解法是因为x*1+y*2+z*5=100,所以得到x*1+y*2=100-z*5

又因为z<=20,x<=100,y<=50

优化后的代码:

 public static int CountC()
        {
            int number = 0;   //初始化计数器
            for (int m = 0; m <= 100; m += 5)
                number += (m + 2) / 2;
            return number;
        }



转载于:https://www.cnblogs.com/tao-zi/p/3832573.html

大范围计算组合数可以采用不同的算法,下面为你介绍几种常见的方法: ### 动态规划法 动态规划是解决组合数问题的经典方法。其核心思想是利用组合数的递推公式 \(C(n, m) = C(n - 1, m) + C(n - 1, m - 1)\),其中 \(C(n, m)\) 表示从 \(n\) 个元素中选取 \(m\) 个元素的组合数。以下是使用动态规划法计算组合数的代码示例: ```python def getc(n, mod): a = [[0] * (n + 1) for _ in range(n + 1)] for i in range(n + 1): for j in range(i + 1): if j == 0: a[i][j] = 1 else: a[i][j] = (a[i - 1][j] + a[i - 1][j - 1]) % mod return a ``` 这种方法的时间复杂度为 \(O(n^2)\),根据复杂度分析,当数据规模在 1000 - 2500 时可以使用该方法,因为按照一秒处理 \(10^8\) 数据规模计算,\(O(N^2)\) 复杂度对应的最大规模在这个范围 [^2][^3]。 ### 浮点数辅助法 利用浮点数可以计算结果在 `double` 表示范围(约 \(10^{308}\))以内的组合数。不过 `double` 类型会损失精度,还可以考虑单用一个 `int` 数记录结尾 0 的个数,用 `double` 表示前面的数,但此算法结果需先保存在 `double` 类型里,还需进一步优化 [^1]。 ### 快速幂 + 乘法逆元法 在取模运算下,当模数为质数时,可以使用快速幂和乘法逆元来计算组合数组合数公式 \(C(n, m)=\frac{n!}{m!(n - m)!}\),在取模运算中,需要计算 \(m!(n - m)!\) 的乘法逆元。 ```python def quick_pow(a, b, mod): res = 1 while b: if b & 1: res = res * a % mod a = a * a % mod b >>= 1 return res def mod_inverse(x, mod): return quick_pow(x, mod - 2, mod) def combination(n, m, mod): fact = [1] * (n + 1) for i in range(1, n + 1): fact[i] = fact[i - 1] * i % mod numerator = fact[n] denominator = fact[m] * fact[n - m] % mod return numerator * mod_inverse(denominator, mod) % mod ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值