【数论】计算组合数

问题 B(2713): [POJ2249]计算组合数

时间限制: 1 Sec  内存限制: 128 MB

题目描述

给定正整数n, k,计算C(n, k)。答案保证在2^31以内。

输入

多组数据,每组数据仅一行,即2个整数n和k (n>=1) and k (0<=k<=n). 

以2个0结束输入

输出

对每个数据,输出对应的答案 

样例输入

 (如果复制到控制台无换行,可以先粘贴到文本编辑器,再复制)

4 210 549 60 0

样例输出

625213983816

提示

#----------------------------------------------------------------------------------------------#
这种题还需要说吗,大大的水资源啊,怎么能浪费……
思路什么的不说什么了,先看第一次的代码:
#include<cstdio>
#define LL long long//虽然答案保证了在2^31内,但我还是用了longlong,以防万一
LL C(LL x,LL y)
{
    LL sum=1;
    for(int i=1;i<=y;i++)
        sum=sum*(x--)/i;//边乘边除不会有问题,因为我们计算的时候乘是从大到小,除是从小到大,始终都能整除
    return sum;
}
int main()
{
    LL a,b;
    while(1)
    {
        scanf("%lld%lld",&a,&b);
        if(!a&&!b) return 0;
        if(a==b||b==0) {printf("1\n"); continue;}//觉得有可能超时,便加上了这句
        printf("%lld\n",C(a,b));
    }
    return 0;
}
然后真的超时了………………【神尴尬】
所以。。算法肯定不能怎么改了,但我们知道组合数有个重要的性质(m>n):

于是,我们要加上这样一行:
if(b>a-b) b=a-b;
瞬间就1998ms变成了0ms……
正确代码:
#include<cstdio>
#define LL long long
LL C(LL x,LL y)
{
    LL sum=1;
    for(int i=1;i<=y;i++)
        sum=sum*(x--)/i;
    return sum;
}
int main()
{
    LL a,b;
    while(1)
    {
        scanf("%lld%lld",&a,&b);
        if(!a&&!b) return 0;
        if(a==b||b==0) {printf("1\n"); continue;}
        if(b>a-b) b=a-b;
        printf("%lld\n",C(a,b));
    }
    return 0;
}

                                                                                                                                 By WZY


posted @ 2017-02-16 13:42  ∑∞  阅读(185)  评论(0编辑  收藏  举报