计算组合数的几种方法总结

您所在的位置:网站首页 排列cmn怎么算 计算组合数的几种方法总结

计算组合数的几种方法总结

2024-07-12 14:00| 来源: 网络整理| 查看: 265

前言

组合数就是 Cmn C n m ,是排列组合中非常重要的一部分,最近做到了几道与计算组合数有关的题,想在此总结一下如何编程计算组合数。 某位大佬在我之前也写过类似的文章,这是他的博客:https://blog.csdn.net/u010582475/article/details/47707739

递推(杨辉三角)

先给出递推公式: Cmn=Cmn−1+Cm−1n−1 C n m = C n − 1 m + C n − 1 m − 1 证明:从n个数中选m个数,若第n个数不选,则相当于从n-1个数中选m个数,即 Cmn−1 C n − 1 m ;若第n个数选,则相当于从n-1个数中选m-1个数,即 Cm−1n−1 C n − 1 m − 1 。那么总方案数即为两者之和。 当然,也可以根据组合数公式,展开来证明其相等,这里就不写出来了,有兴趣的话也可以自己去推。 如果写成数组形式,就是c[n][m]=c[n-1][m]+c[n-1][m-1],这同时是杨辉三角的递推公式,所以组合数满足杨辉三角。边界是c[0][0]=1。若只要求一个组合数的话,也可以滚动一下这个数组,节约空间,但同时m这一维要倒着枚举,就像01背包一样。程序如下:

#include using namespace std; int n,m; long long c[10005]; int main() { cin>>n>>m; m=min(m,n-m); c[0]=1; for (int i=1;i=1;j--) { c[j]=c[j]+c[j-1]; } } coutm>>p; cout=p的情况下使用的。这样可以减小n和m,使之小于p,再用乘法逆元去求组合数。 其实卢卡斯定理就是一个小优化,大部分和乘法逆元求组合数一样,不过要注意在n=0和m=0时的边界处理。

#include using namespace std; int n,m,p; long long pow(long long x,long long y) { if (y==0) return 1; long long z=pow(x,y/2)%p; if (y%2==0) return z*z%p; return z*z%p*x%p; } long long ni(long long x) { return pow(x,p-2); } long long c(int n,int m) { if (m==0) return 1%p; if (n==0) return 0; if (n>=p||m>=p) return c(n/p,m/p)*c(n%p,m%p)%p;//卢卡斯定理核心语句 long long x=1,y=1; for (int i=n;i>=n-m+1;i--) x=x*i%p; for (int i=1;i>n>>m>>p; coutp; m=min(m,n-m);//小优化 cout


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3