POJ2249_Binomial Showdown

_考查点:

对待写代码的谨慎和数学思维。

_思路:

这个题就是完完全全的求组合数而已,只不过特别需要注意数据范围。

_提交情况:

Wrong Answer很多次。

第一次用的long long类型用组合数公式c(n,m)=p(n,m)/m!=n!/((n-m)!*m!)。分别算了分子和分母

的连续乘积之后才一个除法得出结果,但是一提交就WA了.

第二次,用的组合数公式c(n,m)=c(n-1,m)+c(n-1,m-1)。写了一个递归函数来求(可以避免中间结果的溢出),

但是很不幸,函数调用次数过多,TLE了...

最后一次,用一个sum变量(初始化为1)然后乘一个除一个,这样一直下去,居然鬼使神差的AC了,

现在没明白为什么,应该是有漏洞(中间有除不尽的情况?)...

然后看了另外一个能够AC的解法——对组合数公式两边取对数,然后再算,这样就很好的避免中间结果溢出的问题。

但是这个方法唯一美中不足的是,可能会存在精度的问题,毕竟求对数然后再求回来求指数是用的float或是double类型。

_收获:

越学习越发现自己懂的太少了。在算法这条道路上虽然才起步,但是我相信努力就能成功。路漫漫其修远兮,吾将上下而求索。

_AC的代码(如果有更好的方法还请不吝赐教,谢谢...):

①两边取对数的方法(推导过程见http://wenku.baidu.com/view/059da129ed630b1c59eeb57e.html),

#include <cstdio>
#include <cmath>
//#define GANGAN


int main() {
#ifdef GANGAN
freopen("B_in.txt", "r", stdin);
#endif
int n, m;


while (scanf("%d%d", &n, &m) != EOF) {
if (0 == n && 0 == m)
break;
double a = 0, b = 0;
m = m < n - m ? m : n - m;
for (int i = n - m + 1; i <= n; i++) {
a += log((double)i);
}
for (int j = 1; j <= m; j++) {
b += log((double)j);
}
a -= b;
printf("%.lf\n", exp(a) + 0.1);//0.1是为了避免出现误差
}
return 0;
}
/*
log(x)和wxp(x)都是C的<math.h>里面的函数,
分别问求以e为底数的对数,和求e^x.(e的x次方)
//*/

②一边乘一边除:

#include <cstdio>
//#define GANGAN


int main() {
#ifdef GANGAN
freopen("B_in.txt", "r", stdin);
#endif
int n, k;


while (scanf("%d%d", &n, &k) != EOF) {
   if (0 == n)
            break;
long long sum = 1;
k = k < n - k ? k : n - k;
if (0 == k) {
printf("1\n");
continue;
}
for (int i = 0; i < k; i++) {
            sum *= n - i;
            sum /= i + 1;
}
printf("%lld\n", sum);
}
return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值