题目抽象:有m个手持50元的人,n个手持100元的人,售票处没有准备钱。问有多少种不同的方案使得购票不中断。每个人是不同的个体。
分析:简单DP题。画个格子,那么选取的点不越过对角线y = x. dp[i][j]表示i个100元的人,j个手持50元的人的方案数。 i<=j dp[i][j] = dp[i-1][j]+dp[i][j-1]; i>j dp[i][j] = 0; 如果对某些点有限制,那么在递推是加条件判断。
ans = dp[n][m] * n! * m!; 本题用java处理大数。
1 import java.util.*; 2 import java.io.*; 3 import java.math.*; 4 5 public class Main 6 { 7 static Scanner cin = new Scanner(new BufferedInputStream(System.in)); 8 public final static int MS= 101; 9 public static BigInteger[][] dp = new BigInteger[MS][MS]; 10 public static BigInteger[] fact = new BigInteger[MS]; 11 static 12 { 13 fact[0] = BigInteger.ONE; 14 for(int i =1;i<MS;i++) 15 fact[i] = fact[i-1].multiply(BigInteger.valueOf(i)); 16 17 for(int i =0;i<MS;i++) 18 dp[0][i] = BigInteger.ONE; 19 for(int i =1;i<MS;i++) 20 { 21 for(int j =0;j<MS;j++) 22 { 23 if(j<i) 24 dp[i][j] = BigInteger.ZERO; 25 else 26 dp[i][j] = dp[i-1][j].add(dp[i][j-1]); 27 } 28 } 29 } 30 31 // 画出格子,选择的点不能越过y = x。 32 // dp[i][j] = dp[i-1][j] + dp[i][j-1] // dp[i][j]表示i张100元,j张50元的所有情况。 33 // ans = dp[n][m] * n! *m! ; 34 35 public static void main(String[] args) 36 { 37 int n,m,kase = 1; 38 //System.out.println(dp[0][3].multiply(fact[0]).multiply(fact[3])); 39 while(cin.hasNext()) 40 { 41 m = cin.nextInt(); 42 n = cin.nextInt(); 43 44 if(n == 0 && m == 0) 45 break; 46 System.out.println("Test #" + (kase++) +":"); 47 System.out.println(dp[n][m].multiply(fact[n]).multiply(fact[m])); 48 } 49 } 50 }
时间: 2024-10-18 23:47:32