ps:
c(n,m) = n!/(m!*(n-m)!)
如果n和m比较大时 可能会导致中间超过数据范围,不过我们可以直接用递推也就是
c(n,m) = c(n-1,m)+c(n-1,m-1)
不过下面我们要用另外一种方法来计算这个组合
把分子和分母约掉之后就变成了
(n*(n-1)*……*(n-m+1))/m!
这样上面和下面都是m个元素,我们可能会想到乘1个除1个,这样来避免越界,可是这样会刚好整除吗?不会出现小数使得最后的答案变错吗?其实只要我们按照一定的顺序来乘和除的话,是不会产生小数的,也就是说会一直整除的.
首先我们把上面那个分数写成这样的
(n*(n-1)*……*(n-m+1))/(m*(m-1)*……*1)
这样的话就相当于n–>m
下面先给出主要程序吧
f = 1;//最后答案
for(i = 1;i <= m;i++)
现在主要的是要说明每次乘以(i+(n-m))然后再除以i不会产生小数,我是这么想的,说先i是1,肯定不会有小数,然后i=2,但是分母已经乘过两个数了,肯定有一个奇数,一个偶数,也不会产生小数,同理3的时候也不会,但是4的时候可能会这样想,前面某个数k整除4,那已经别2除掉了一个2,这样会不会产生小数呢?结果是不会的,因为4个相当于2个2,或者1个4,我们可以把除2的那个选择到这4个当中不能出4的那一个数上,这样的话,就剩下了一个能整除4的了,然后其他的就和这里一样了。
#include"stdio.h" int main() { int t,n,m,i; double sum; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); if(n<m) { printf("0\n"); continue; } sum=1; for(i=1;i<=m;i++) sum*=(n+1-i)/(double)i; printf("%.0f\n",sum); } return 0; }