【数论】计算组合数

来源:互联网 发布:阿里云服务器地域 编辑:程序博客网 时间:2024/04/27 15:42

问题 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 longLL 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


0 0
原创粉丝点击