Problem Description
开学了,杭电又迎来了好多新生。ACMer想为新生准备一个节目。来报名要表演节目的人很多,多达N个,但是只需要从这N个人中选M个就够了,一共有多少种选择方法?
Input
数据的第一行包括一个正整数T,接下来有T组数据,每组数据占一行。 每组数据包含两个整数N(来报名的人数,1<=N<=30),M(节目需要的人数0<=M<=30)
Output
每组数据输出一个整数,每个输出占一行
Sample Input
5 3 2 5 3 4 4 3 6 8 0
Sample Output
3 10 1 0 1
刚开始的思路
二项式系数C(n, k)满足下面的要求:
C( n, 0) = C( n, n) = 1 for all n > 0; C( n, k) = C( n − 1, k − 1) + C( n − 1, k) for all 0 < k < n.
题目要求根据给定的n和k(0 ≤ k ≤ n < 2 31, n > 0)计算C(n,k),典型的递归问题。
但是如果采用递归,当n的值比较大的时候,会堆栈益处。而上面的表达式应该有相应的公式。如果采用公式计算就会变的简单了。
但是总是WA,最后发现是超出范围!!!
1 #include2 #include 3 using namespace std; 4 int zuhe(int n,int k) 5 { 6 int *result = new int[n]; 7 for(int i=1;i<=n;i++) 8 { 9 result[i] = 1;10 for(int j=i-1;j>=1;j--)11 {12 result[j] = result[j-1]+result[j];13 }14 result[0] = 1;15 }16 return result[k];17 }18 int main()19 {20 int t;21 scanf("%d",&t);22 while(t--)23 {24 int a,b;25 scanf("%d%d",&a,&b);26 if(b>a)27 {28 printf("0\n");29 continue;30 }31 printf("%d\n",zuhe(a,b));32 }33 return 0;34 }
可以这样:
1 #include2 using namespace std; 3 int c[31][31]; 4 int main() 5 { 6 int i,j; 7 for(i=1;i<31;i++) 8 {c[i][0]=1;c[i][1]=i;} 9 for(i=2;i<31;i++)10 for(j=2;j<=i;j++)11 c[i][j]=c[i-1][j]+c[i-1][j-1];12 int t,n,m;13 while(scanf("%d",&t)!=EOF)14 {15 while(t--)16 {17 scanf("%d%d",&n,&m);18 printf("%d\n",c[n][m]);19 }20 }21 return 0;22 }
之后通过了解:
1 #include2 #include 3 using namespace std; 4 int main(void) 5 { 6 int m,n,t; 7 long long sum; 8 cin>>t; 9 while(t--)10 {11 cin>>n>>m;12 sum=1;13 for(int i=1;i<=m;i++)14 {15 sum*=n--;16 sum/=i;17 }18 printf("%lld\n",sum);19 }20 return 0;21 }