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();
	}
}



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