因為我忘記做gcd惹 @_@。
題目有說不會超過32-bit,所以用int即可。
排列公式把分母(N - M)!或是M!與分子化簡。
變成分子為(N - M + 1) * (N - M + 2) * ... * N
分母為1 * 2 * 3 * ... * M。
因為答案一定是整數,所以分母一定可以被分子化簡,
注意!
如果遇到不能化簡,要找gcd化簡,
例如:15 7,這種組合就要找gcd。
沒找gcd直接化簡就gg了。 @_@。
N - M跟M,較小的留下來,大的做化簡即可。
/* ACM 369 Combinations
* mythnc
* 2011/10/29 16:51:07
* run time: 0.008
*/
#include <stdio.h>
#define MAXARY 50
int com(int, int);
int gcd(int, int);
int main(void)
{
int m, n;
while (scanf("%d %d", &n, &m)) {
if (n == 0 && m == 0)
return 0;
printf("%d things taken %d at a time is %d exactly.\n"
, n, m, com(n, m));
}
}
/* com: return the combined times */
int com(int n, int m)
{
int i, j, factor, tmp;
int num[MAXARY];
if (m == n || m == 0)
return 1;
if (m > n - m)
m = n - m;
/* init */
for (i = 0; i < m; i++)
num[i] = n - m + 1 + i;
/* simplify */
for (i = m; i > 1; i--) {
tmp = i;
for (j = 0; j < m; j++) {
if (num[j] % tmp == 0) {
num[j] /= tmp;
break;
}
factor = gcd(tmp, num[j]);
if (factor > 1) {
tmp /= factor;
num[j] /= factor;
}
}
}
/* product */
for (i = 1; i < m; i++)
num[0] *= num[i];
return num[0];
}
/* gcd: return the gcd of a and b */
int gcd(int a, int b)
{
while ((a %= b) && (b %= a))
;
return a + b;
}
沒有留言:
張貼留言