ZOJ 3380 Patchouli's Spell Cards

方案数,$dp$。

总的方案数有$n^m$种,符合要求的直接算不好算,可以算反面,即不符合要求的。

设$dp[i][j]$表示前$i$种等级填了$j$个位置,那么$dp[i][j]=sum(dp[i-1][j-k]*c[m-(j-k)][k])$。初始化$dp[0][0]=1$。

符合要求的方案数为$n^m-dp[n][m]$。数字会爆$long$ $long$,上$java$。

import java.math.BigInteger;
import java.util.Scanner;

public class Main {
    
    public static BigInteger GCD(BigInteger a,BigInteger b)
    {
        if(b.equals(BigInteger.ZERO)) return a;
        return GCD(b,a.mod(b));
    }
    
    public static void main(String [] args)
    {
        Scanner cin = new Scanner(System.in);
        int M,N,L;
        
        BigInteger c[][] = new BigInteger[105][105];
        BigInteger dp[][] = new BigInteger[105][105];
        
        for(int i=0;i<=100;i++)  c[i][0] = c[i][i] = BigInteger.ONE;
        for(int i=1;i<=100;i++)
        {
            for(int j=1;j<i;j++)
            {
                c[i][j]= c[i-1][j-1].add(c[i-1][j]);
            }
            for(int j=i+1;j<=100;j++) c[i][j] = BigInteger.ZERO;
        }
        
        while(cin.hasNext())
        {
            M=cin.nextInt();
            N=cin.nextInt();
            L=cin.nextInt();
            
            if(L>M) System.out.println("mukyu~");
            else 
            {
                
                BigInteger n = BigInteger.valueOf(N);
                
                BigInteger fm = n.pow(M);
                BigInteger fz = new BigInteger("0");
                
                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-1;k++)
                        {
                            if(j-k<0) continue;
                            if(M-(j-k)<0) continue;
                            
                            dp[i][j] = dp[i][j].add(dp[i-1][j-k].multiply(c[M-(j-k)][k]));
                        }
                    }
                }
                
                fz=dp[N][M]; fz = fm.subtract(fz);
                BigInteger gcd = GCD(fz,fm);
                fz=fz.divide(gcd); fm=fm.divide(gcd);
                System.out.println(fz+"/"+fm);
                
            }
        }
    }
}

 

posted @ 2017-01-21 17:16  Fighting_Heart  阅读(181)  评论(0编辑  收藏  举报