求C n m(从n个数中选m个数,有多少种组合?问题)暴力—递归——回归数学公式,三种方法,层层优化!
文章将以代码+解析(简单)的方式进行,欢迎大家的阅读!
首先,任何一个问题都是有来源的,所以请先看题(我遇到的):
暴力解法(我第一次的想法)
代码如下:
#include <stdio.h>
int main() {int n, m, i, num;scanf("%d", &num);while (num--) {scanf("%d %d", &n, &m);int N = 1;for (i = 1; i <= n; i++) {N *= i;}int M = 1;for (i = 1; i <= m; i++) {M *= i;}int N_M = 1;for (i = 1; i <= n - m; i++) {N_M *= i;}int f = N / (M * N_M);printf("%d\n", f);}return 0;
}
核心:数学公式:n!/(m!*(n-m)!)
所以我们只需要分别算三次阶乘(对应代码N ,M ,N_M)就OK了,非常暴力,但最容易理解!
缺点:计算速度慢,当数据大的时候,就报不过去了,因为已经超过long long类型了(于是我进行了第二种方法——递归)。
但如果数据不大,代码跑的结果是没有任何问题的。
请看一下上述问题的测试数据:
递归解法(进一步优化)
代码如下:(仅单次输入)
#include <stdio.h>
long long f(int n, int m)
{if (n < m) return 0;//分几种情况if (n == m) return 1;if (m == 0) return 1;return f(n - 1, m - 1) + f(n - 1, m);//实现递归
}
int main()
{int n, m;long long k = 0;scanf("%d %d", &n, &m);k = k + f(n, m);printf("%lld", k);return 0;
}
核心:递归
如果不好理解请看下面,我将用图片来讲解这个递归。
我只是随便找了一个例子,当然有人会说C 6 2不是要比C 6 4要好进行嘛,是的没错,我在这里先埋下一个伏笔,最后我会针对这个问题进行优化(指的是第三种方法的优化)!
通过这个图片,大家应该可以很好的理解这个递归。
回归数学方法(加优化)
代码如下(仅单次输入):
#include<stdio.h>
int main()
{double n, m;scanf("%lf %lf", &n, &m);double sum = 1;double i;double q = m;for (i = 1; i <= q; i++){sum *= (n--) / (m--);}printf("%.0lf", sum);return 0;
}
核心:数学方法
不知道怎么描述,所以直接暴力上图(高中数学知识):
我再解释一下我的代码:
C n m, m就是我循环的次数,为了m的值在m--的时候不会丢失,我在这里用q存储一下m的值,使得循环正常进行。
最后来到了优化环节:
举个例子C 6 4 与 C 6 2的值是一样的,前者循环4次,后者循环2次,为了减少循环次数,只需加上一个判断处理一下m的值,具体我直接上代码:
int q;if (n - m < m) {q = n - m;m = q;}elseq = m;
这样就可以使代码运行时,用最小的循环次数来进行!
在最后我附上最终代码(C与C++)
C:
#include<stdio.h>
int main()
{double n, m;int T;scanf("%d", &T);while (T--){scanf("%lf %lf", &n, &m);int q;if (n - m < m){q = n - m;m = q;}elseq = m;double t = 1;for (int i = 1; i <= q; i++)t *= (n--) / (m--);printf("%.lf\n", t);}return 0;
}
C++(学长提供):
在文章最开头我提到的问题,用最后一种代码跑没有一点问题。因为在乘的过程中 除也在进行,就可以保证内存够用。
此题花费我数小时来解决(我太菜了,滑稽保命!)
希望本篇文章可以很好为广大老铁们解疑答惑,同时也希望老铁们留下宝贵的建议与指导。
最后再次感谢您的阅读!
求C n m(从n个数中选m个数,有多少种组合?问题)暴力—递归——回归数学公式,三种方法,层层优化!相关推荐
- 从m个中选n数php语言,18-从n个数中选m个
#include using namespace std; int f(int n, int m){ if(n < m) //这个条件必须先判断,因为递归时n-1了,可能有这种情 ...
- 求超定方程组最小二乘解的三种方法
目录 1.超定线性方程组与最小二乘解 2.求解超定方程组的三种方法 3.参考链接 1.超定线性方程组与最小二乘解 超定线性方程组:方程的个数大于解个数,方程组是无解的,但是我们可以求得其最小二 ...
- C语言求最大公约数的三种方法
最大公约数是两个数可以同时整除的数中最大的那个 这里用三种方法来解决 穷举法求最大公约数 判断x和y的最大公约数,x和y其中一定有一个相对较小的数,然后从这个较小数开始遍历,不断地用x和y去除这个数, ...
- C++语言递归实现求从n个数中选k个进行组合的组合数
C++语言递归实现求从n个数中选k个进行组合的组合数 公式: 需要注意结束条件和递推公式的使用. 递归需要用到函数的思想,此处定义一个fun()函数用于求组合数,记住,一旦调用fun()函数,如:fu ...
- 求一个数的因子个数/因子和/质因子 C/C++实现
求一个数的因子个数时间复杂度O√n ll get_number(ll x){ll num=0;for(ll i=1;i*i<=x;i++){if(x%i==0) num+=2; if(i*i== ...
- 求有多少个数是这个数的约数
引入问题 给你一个长度为nnn的数组,对于里面每一个数求出数组里有多少个数是这个数的约数[除了这个数之外] 解决问题: 逆向思维去枚举质数. acwing1293 #include <bits/ ...
- 编程笔试(解析及代码实现):序列重排之给一个长度为n的序列A,求找出某种排列方式使得相邻两个数的差值之和最大并求出该最大值
编程笔试(解析及代码实现):序列重排之给一个长度为n的序列A,求找出某种排列方式使得相邻两个数的差值之和最大并求出该最大值 目录 题目描述 代码实现 题目描述 序列重排:给一个长度为n的序列A,求找出 ...
- 从str中选 m 个数的所有排列算法
// 从str中选 m 个数的所有排列算法 void perm(string str,int a,int b,int m){ // 字符数达到 m 个进行输出 if(a==m){for(int i=0 ...
- python求斐波那契数列第n个数及前n项和_使用python求斐波那契数列中第n个数的值示例代码...
斐波那契数列(Fibonacci sequence),又称黄金分割数列.因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为"兔子数列&qu ...
最新文章
- c语言程序开平方,关于开平方的c程序
- Java自学路线总结,已Get腾讯Offer
- 一文读懂因果推断的起源
- [Android] 基于 Linux 命令行构建 Android 应用(四):命令行构建
- struts2文件上传一个错误的解决
- 河南理工大学python挂科率_河南高校2021届保研率排名,上榜仅有10所,河南理工大学第6...
- 语音识别行业成长红利期已过,行业寡头显现,小公司生存状况堪忧
- Java基础学习(3)-泛型
- 嵌入式系统开发项目管理
- 日本公司为东京大学开设区块链课程捐款80万美元
- 韦根协议-C编程实现
- 什么是容器服务_即学即用Docker(一):说说容器和Docker
- python连接服务器执行命令进行部署
- 微信小程序快捷键和windows快捷键
- mca版Quiver快速入门
- ROSNOTE : ros::spin() / ros::spinOnce() /rospy.spin()
- NYOJ 495 少年 DXH
- IFS认证咨询,关于家用和个人护理产品安全和质量的发展和评估项目
- 任务7、统计一组学生成绩
- 世界经济论坛公布全球首个量子计算标准指南
热门文章
- 设计模式 - 七大设计原则(一)
- java 课后习题 三角形面积计算
- C#LeetCode刷题之#599-两个列表的最小索引总和​​​​​​​​​​​​​​(Minimum Index Sum of Two Lists)
- 面向对象设计原则之1-单一职责原则
- 手机测评系列之vivox23
- javascript 框架_我们仍然需要JavaScript框架吗?
- glide 加载webp_如何使您的网站通过WebP图像快速加载闪电
- 动态瑜伽 静态瑜伽 初学者_瑜伽与编程有什么关系?
- 机器学习与分布式机器学习_这就是为什么任何人都可以学习机器学习的原因
- 使用Python进行汽车黑客攻击:泄露GPS和OBDIICAN总线数据