ZOJ 3380 Patchouli's Spell Cards——组合数+概率dp

题意:

m个位置,每个位置可以等概率填n种数,规定一个数字出现次数不能超过L次(注意不是连续L次),填完m个位置后满足约束的概率是多少。

思路:

定义dp[i][j]为前i种数字填充j个位置(j个位置不必连续)的方案数,那么

dp[i][j]=∑(1<=k&&k<L&&k<=j)dp[i-1][j-k]*C[m-(j-k)][k],C为组合数

结果就是(n^m-dp[n][m])/n^m

import java.util.*;
import java.io.*;
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));
		C[0][0] = BigInteger.ONE;
		for (int i = 1; i <= 100; i++) {
			C[i][0] = C[i][i] = BigInteger.ONE;
			for (int j = 1; j < i; j++) {
				C[i][j] = C[i-1][j].add(C[i-1][j-1]);
			}
		}
		int m, n, l;
		while (cin.hasNext()) {
			m = cin.nextInt(); n = cin.nextInt(); l = cin.nextInt();
			if (l > m) {
				System.out.println("mukyu~");
				continue;
			}
			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 = 0; j <= m; j++) {
					for (int k = 0; k < l && k <= j; k++) {
						dp[i][j] = dp[i][j].add(dp[i-1][j-k].multiply(C[m-(j-k)][k]));
					}
				}
			}
			BigInteger y = BigInteger.valueOf(n).pow(m);
			BigInteger x = y.subtract(dp[n][m]);
			BigInteger z = x.gcd(y);
			x = x.divide(z);
			y = y.divide(z);
			System.out.println(x+"/"+y);
		}
		cin.close();
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值