解析:  组合问题。题目的意思就是要求C(n,m).高中时学过

        C (n,m)  =  n! / (m! * (n - m)!)      

      当然不能求出阶乘,只能逐步相乘,逐步约分,防止溢出。分子是从n - m + 1乘到n,分母是从1乘到m,都进行了m - 1次乘法!!

     如果每一次消去他们的最大公约数,就也许能保证不溢出。

      为了保证不超时,还需要优化,即 C (n,m)  =  C (n,n-m)   如果 n-m<m,应该令 m = n - m;

 1 #include <stdio.h>
 2 typedef long long llong;
 3 llong gcd(llong m, llong n)      /*求最大公约数*/
 4 {
 5     llong temp;             
 6     if(n > m){
 7         temp = n;
 8         n = m;
 9         m = temp;
10     }
11     while(n != 0){          
12         temp = m % n;      
13         m = n;             
14         n = temp;          
15     }
16     return m;
17 }
18 
19 int main()
20 {
21     llong n, m;
22     llong i, j, fz, fm, temp;
23     while(scanf("%lld%lld", &n, &m) == 2 && n + m){
24         fz = fm = 1;
25         if(n - m < m)
26             m = n - m;
27         for(i = 1, j = n; i <= m; i++, j--){
28             fz *= j;
29             fm *= i;
30             temp = gcd(fz, fm);
31             fz /= temp;
32             fm /= temp;
33         }
34     printf("%lld\n", fz / fm);
35     }
36     return 0;
37 }

 

 

 

 

我们还学过一个公式        C(n,m)=C(n-1,m-1)+C(n-1,m)   但是一定会超时的。超时的代码如下:

 1 //Time Limit
 2 #include <stdio.h>
 3 int C(int n, int m)
 4 {
 5     if(m == 0 || n == m)
 6         return 1;
 7     if(m == 1 || m == n - 1)
 8         return n;
 9     return C(n - 1, m - 1) + C(n - 1, m);
10 }
11 
12 int main()
13 {
14     int n, m;
15     while(scanf("%d%d", &n, &m) == 2 && n + m)
16         printf("%d\n", C(n,m));
17     return 0;
18 }