ZOJ 3380 Patchouli's Spell Cards [基础DP+大数]

Description

Patchouli Knowledge, the unmoving great library, is a magician who has settled down in the Scarlet Devil Mansion (红魔馆). Her specialty is elemental magic employing the seven elements fire, water, wood, metal, earth, sun, and moon. So she can cast different spell cards like Water Sign "Princess Undine"Moon Sign "Silent Selene" and Sun Sign "Royal Flare". In addition, she can combine the elements as well. So she can also cast high-level spell cards like Metal & Water Sign "Mercury Poison" and Fire, Water, Wood, Metal & Earth Sign "Philosopher's Stones" .

Assume that there are m different elements in total, each element has n different phase. Patchouli can use many different elements in a single spell card, as long as these elements have the same phases. The level of a spell card is determined by the number of different elements used in it. When Patchouli is going to have a fight, she will choose m different elements, each of which will have a random phase with the same probability. What's the probability that she can cast a spell card of which the level is no less than l, namely a spell card using at least l different elements.


题意:

抽象的来说,就是给你M个不同的球,N种颜色,现在给球染色,问至少有L个球同一种颜色的概率。


范围:

N,M,L<=100


解法:

总方案数很好算,为N^M,剩下的就是求至少L个球同色的方案数,其可以转换为 (总方案数-每种颜色至多L-1个球的方案数)。

然后就是很明显的DP了,DP[I][J]表示已放完I种颜色,剩下J个球的方案数,那么转移方程为

DP[I+1][J-K]+=DP[I][J]*C(J,K) 其中C()为组合数,K为当前颜色装的球数。

注意会暴longlong,需要用大数,我这里使用了JAVA写大数


import java.math.BigInteger;
import java.util.Scanner;
public class Main{
	static BigInteger[][] dp = new BigInteger[111][111];
	static BigInteger[][] c = new BigInteger[111][111];
	static void init(){
		c[0][0]=BigInteger.valueOf(1);
		for(int i=1;i<=100;i++){
			c[i][0]=c[i][i]=BigInteger.valueOf(1);
			for(int j=1;j<i;j++){
				c[i][j]=c[i-1][j-1].add(c[i-1][j]);
			}
		}
	}
	static int min(int x,int y){
		return x<y?x:y;
	}
	static void solve(int m,int n,int l){
		BigInteger fm=BigInteger.valueOf(n).pow(m);
		for(int i=0;i<=n+1;i++)
			for(int j=0;j<=m;j++)dp[i][j]=BigInteger.ZERO;
		dp[0][m]=BigInteger.ONE;
		for(int i=0;i<n;i++){
			for(int j=0;j<=m;j++){
				for(int k=0;k<=min(j,min(m,l-1));k++){
					dp[i+1][j-k]=dp[i+1][j-k].add(dp[i][j].multiply(c[j][k]));
				}
			}
		}
		BigInteger fz=dp[n][0];
		BigInteger gcd=fm.gcd(fz);
		fz=fm.subtract(fz).divide(gcd);
		fm=fm.divide(gcd);
		System.out.println(fz+"/"+fm);
	}
	public static void main(String[] args) {
		init();
		int m,n,l;
		Scanner sc = new Scanner(System.in);
		while(sc.hasNext()){
			m=sc.nextInt();
			n=sc.nextInt();
			l=sc.nextInt();
			if(l>m)System.out.println("mukyu~");
			else solve(m,n,l);
		}
		sc.close();
	}
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章