问题 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 "); continue;}//觉得有可能超时,便加上了这句 printf("%lld ",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 "); continue;} if(b>a-b) b=a-b; printf("%lld ",C(a,b)); } return 0; }
By WZY