自我标记:排列组合问题,计算阶乘的方法
垃圾小玲的题解
UVA369 Combinations
这题的主要问题在于,就算是long也装不下(100!),要怎么规划,让最后的结果能装在一个long里面,而中间结果不溢出。
主要的算法设计就是,分子分母约分。话不多说,看代码。
import java.util.Scanner;
import java.util.*;
public class Main {
public static int gcd(int a,int b) {//获取最大公约数
return (b==0)?a:gcd(b,a%b);//三目运算符
}
public static void main(String[] args) {
Scanner reader=new Scanner(System.in);
int m,n;
int [] a=new int[100]; //数组声明格式
while(reader.hasNext()) {
n=reader.nextInt();
m=reader.nextInt();
if(m==0&&n==0) {
break;
}
long sum=1;
int low=0,top=0,i=0,j=0,k=0,x=0;
//low记录分子阶乘的起点,top记录分母阶乘的终点
//C(n,m)和C(n,n-m)是一样的,if-elif使得分子和分母没有同样的因子
if(m>n-m-1) {
//C(n,n-m)
low=m+1;
top=n-m;
}
else {
//C(n,m)
low=n-m+1;
top=m;
}
//把分子存在a里,等会约分的时候用
for(i=1;i<=top;i++) {
a[i]=i;
}
//遍历分子,每次分子都去找分母的每一个元素约分,直到为1或者遍历完分母
for(i=low;i<=n;i++) {
k=i;
for(j=2;j<=top;j++) {
x=gcd(k,a[j]);
while(a[j]!=1&&x!=1) {
k/=x;
a[j]/=x;
x=gcd(k,a[j]);
}
}
sum*=k;
}
System.out.println(n+" things taken "+m+" at a time is "+sum+" exactly.");
}
}
}