题目大意:
用(1 2 3 ... n) n个数填充 m个位置,问最少相同的数字出现的数量不少于I 的概率
思路分析:
逆向思考,求铺满最多的数量不够I 个的方案数。
每次用一个数字去铺,铺M个位置,每个数字最多铺 不够I个。
dp[i][j]表示枚举到了第i个数字,前i个数字铺了j个位置的方案数。
考虑到组合计数
用Java
import java.util.*; import java.io.BufferedInputStream; import java.math.*; public class Main{ static BigInteger [][] C = new BigInteger[110][110]; static BigInteger [][] dp = new BigInteger[110][110]; public static void main(String args[]){ Scanner cin = new Scanner(new BufferedInputStream(System.in)); for(int i=0;i<105;i++){ C[i][0]=C[i][i]=BigInteger.ONE; for(int j=1;j<i;j++){ C[i][j] = C[i-1][j-1].add(C[i-1][j]); } } int n,m,l; while(cin.hasNext()){ m = cin.nextInt(); n = cin.nextInt(); l = cin.nextInt(); BigInteger total = BigInteger.valueOf(n).pow(m); if(m<l){ System.out.println("mukyu~"); continue; } else if(l>m/2){ BigInteger ans = BigInteger.ZERO; for(int i=l;i<=m;i++){ ans = ans.add(C[m][i].multiply(BigInteger.valueOf(n-1).pow(m-i))); } ans = ans.multiply(BigInteger.valueOf(n)); BigInteger gcd = ans.gcd(total); System.out.println(ans.divide(gcd)+"/"+total.divide(gcd)); } else { for(int i=0;i<=n;i++){ for(int j=0;j<=m;j++) dp[i][j] = BigInteger.ZERO; } dp[0][0] = BigInteger.ONE; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ for(int k=0;k<=j&&k<l;k++){ dp[i][j] = dp[i][j].add(dp[i-1][j-k].multiply(C[m-(j-k)][k])); } } } BigInteger ans = BigInteger.ZERO; for(int i=1;i<=n;i++){ ans = ans.add(dp[i][m]); } ans = total.subtract(ans); BigInteger gcd = ans.gcd(total); System.out.println(ans.divide(gcd)+"/"+total.divide(gcd)); } } } }
Zoj 3380 Patchouli's Spell Cards (概率dp)
时间: 2024-11-07 13:07:09