题目意思:m个人有50元,n个人有100元,现在要在一个窗口买50元的东西,但是窗口没零钱,问你有多少种排列方法?
解题思路:
解法一:
把m个人看成相同的人,n个人看成相同的,那么就相当于入栈和出栈(因为满足出栈的元素必须先入栈的规则),所以我们想到了卡特兰数=>有ans=m!*n!*( (m+n)Cn - (m+n)C(n-1) )
解法二:
采用动态规划的思想,设dp[i] [j]表示有i个50,j个100的排列数目,显然有状态转移方程:dp[i] [j] =dp[i-1] [j] + dp[i] [j-1]
注意:高精度+乘上n!*m!
以下是java代码:
//package hello;//要注释掉
import java.util.*;
import java.io.BufferedInputStream;
import java.math.BigDecimal;
import java.math.BigInteger;
public class Main{
static BigInteger fact(int x){
BigInteger tmp=BigInteger.ONE;
for(int i=2;i<=x;++i) tmp=tmp.multiply(BigInteger.valueOf(i));
return tmp;
}
static Scanner sc = new Scanner (new BufferedInputStream(System.in));
public static void main(String[] args){
int n,m,t=1;
BigDecimal mod1 = new BigDecimal("1E+100");
BigInteger mod = mod1.toBigInteger();
BigInteger one =BigInteger.valueOf(1);
BigInteger two = BigInteger.valueOf(2);
BigInteger dp[][] = new BigInteger [210][210];
while(sc.hasNext())
{
m=sc.nextInt();
n=sc.nextInt();
if(n==0&&m==0) break;
for(int i=0;i<=m;++i) dp[0][i]=one;
for(int i=1;i<=n;++i)
{
for(int j=0;j<=m;++j)
{
dp[i][j]=BigInteger.ZERO;
if(i>j) continue;
else
{
BigInteger tmp=BigInteger.ZERO;
tmp=tmp.add(dp[i-1][j]);tmp=tmp.add(dp[i][j-1]);
dp[i][j]=dp[i][j].add(tmp);
}
}
}
System.out.println("Test #"+(t++)+":");
System.out.println(dp[n][m].multiply(fact(n)).multiply(fact(m)));
}
}
}
由于一些稀奇古怪的元原因,我在输出格式上出现了错误,于是我把输出的格式拆解为了两个部分,就ac了