ZOJ 3380 Patchouli's Spell Cards(概率+大数)

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3957

题意:m个位置,每个位置可以放n种数字(1-n)。问至少有L个位置数字一样的概率?

思路:反着想,我们先求出没有L个位置数字一样的放法ans。dp[i][j]表示前i种数字占据j个位置的放法数,dp[i][j]=sum(dp[i-1][j-k]*C[m-(j-k)][k])(k<L)。则ans=sum(dp[i][m])。则真正的答案Ans=n^m-ans。

import java.util.*;

import java.math.*;



public class Main{

    static BigInteger dp[][]=new BigInteger[105][105];

    static BigInteger C[][]=new BigInteger[105][105];

    

    

    public static void puts(String s){

        System.out.println(s);

    }

    

    public static void main(String[] args){

        

        int i,j,k;

        BigInteger one=BigInteger.ONE,zero=BigInteger.ZERO;

        for(i=0;i<=100;i++){

            C[i][0]=C[i][i]=one;

            for(j=1;j<i;j++) C[i][j]=C[i-1][j-1].add(C[i-1][j]);

        }

        

        int n,m,L;

        Scanner S=new Scanner(System.in);

        while(S.hasNext()){

            

            m=S.nextInt();

            n=S.nextInt();

            L=S.nextInt();

            if(L>m)

            {

                puts("mukyu~");

                continue;

            }

            for(i=0;i<=n;i++) for(j=0;j<=m;j++) dp[i][j]=zero;

            dp[0][0]=one;

            for(i=1;i<=n;i++) for(j=1;j<=m;j++) for(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 ans=zero;

            for(i=1;i<=n;i++) ans=ans.add(dp[i][m]);

            BigInteger tot=BigInteger.valueOf(n).pow(m);

            ans=tot.subtract(ans);

            BigInteger gcd=ans.gcd(tot);

            ans=ans.divide(gcd);

            tot=tot.divide(gcd);

            System.out.println(ans+"/"+tot);

        }

    }

}

  

你可能感兴趣的:(SPEL)