有关组合数越界的问题
2017-12-08 20:46
155 查看
最近周考做到这样一个题,本自信满满,却花费了大量时间也找不到bug在哪里。
题目内容:
n个人中选出k个人参加表演,求有多少种选法。
看起来很好,但是实际上函数在多次递归可能越界了。于是我将int改为long long。由此可见,编写函数并不困难。写完之后的函数可以像cos、sqrt等库函数一样被调用。“别忘了测试!”如果你这样说,请为自己鼓掌。还记得那个“阶乘”之和的第一个程序吗?那个程序溢出了。那这个程序呢?很不幸:当m,k的值稍微大一点的时候,y的值竟然变成了-1。
即使最终答案在所选择的数据类型范围之内,计算的中间结果仍然可能溢出。
正确代码如下:
这个题目还说明:即使认为题目在“暗示”你使用某种语言特性,也应该深入分析,不能贸然行事。如何避免中间结果溢出?办法是进行“约分”。一个简单的方法是利用n!/m!=(m+1)(m+2)…(n-1)n。虽然不能完全避免中间结果溢出,但是对于题目给出的范围已经可以保证得到正确的结果了。
题目内容:
n个人中选出k个人参加表演,求有多少种选法。
//我第一次的代码是这样 #include <stdio.h> int fac(int n) { int f; if(n==0) f=1; else f=fac(n-1)*n; return f; } int main() { // write your code here int m,k,l; int y; scanf("%d%d",&m,&k); l=m-k; y=fac(m)/(fac(k)*fac(l)); printf("%d",y); return 0; }
看起来很好,但是实际上函数在多次递归可能越界了。于是我将int改为long long。由此可见,编写函数并不困难。写完之后的函数可以像cos、sqrt等库函数一样被调用。“别忘了测试!”如果你这样说,请为自己鼓掌。还记得那个“阶乘”之和的第一个程序吗?那个程序溢出了。那这个程序呢?很不幸:当m,k的值稍微大一点的时候,y的值竟然变成了-1。
即使最终答案在所选择的数据类型范围之内,计算的中间结果仍然可能溢出。
正确代码如下:
#include <stdio.h> int compute(int n, int k) { if (k == 0) { return 1; } else { return (n * compute(n - 1, k - 1)) / k; } } int main() { int m, n; scanf("%d %d", &m, &n); printf("%d\n", compute(m, n)); return 0; }
这个题目还说明:即使认为题目在“暗示”你使用某种语言特性,也应该深入分析,不能贸然行事。如何避免中间结果溢出?办法是进行“约分”。一个简单的方法是利用n!/m!=(m+1)(m+2)…(n-1)n。虽然不能完全避免中间结果溢出,但是对于题目给出的范围已经可以保证得到正确的结果了。
相关文章推荐
- 3.C语言凯撒密码(有关缓冲区)以及数组越界问题
- 一个有关C语言浮点数保留2位小数的操蛋问题
- 由于本人不再从事Kinect相关的开发工作,有关与kniect的问题没有办法一一回答,本专辑不再更新。
- 有关Lucene的问题(4):影响Lucene对文档打分的四种方式
- bzoj 4870: [Shoi2017]组合数问题 [矩阵乘法优化dp]
- 有关eclipse连接SQL Server 2008的问题
- 解决vc++DEBUG ERROR问题前几天师弟调试程序的时候出现了这样一个错误,出错的位置是在delete [] 一个动态分配的数组时出现的。 经过调查发现错误是因为他之前在给数组赋值的时候越界了
- 有关子类构造函数的问题
- 有关FragmentDialog的细节问题
- 有关Spring+Java实现国际化的若干小问题
- 有关cvLaplace函数和cvSobel函数的参数及显示处理后的图片问题
- 有关ListView注意的问题
- 微信小程序——有关清除template中的input数据问题
- 有关素数的问题
- [六省联考2017]组合数问题
- [BZOJ4870][SHOI2017]组合数问题 DP+矩阵快速幂
- 有关域环境下的SID号的问题
- 有关射线层级和碰撞层级的问题
- 类的初始化问题(初始化顺序与定义的位置前后有关)
- Noip2016day2 组合数问题problem