• ZOJ 3380 Patchouli's Spell Cards(概率DP)


    Patchouli's Spell Cards

    Time Limit: 7 Seconds      Memory Limit: 65536 KB

    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.

    Input

    There are multiple cases. Each case contains three integers 1 ≤ m, n, l ≤ 100. Process to the end of file.

    Output

    For each case, output the probability as irreducible fraction. If it is impossible, output "mukyu~" instead.

    Sample Input

    7 6 5
    7 7 7
    7 8 9
    

    Sample Output

    187/15552
    1/117649
    mukyu~
    

    References

    上海アリス幻樂団

    acm_x_touhou


    Author: WU, Zejun
    Source: ACM × Touhou
    Contest: ZOJ Monthly, August 2010

    /*
     * ZOJ 3380
     * 题目意思:有m个位置,每个位置填入一个数,数的范围是1~n,问至少有L个位置的数一样的概率
     * 输出要是最简分数的形式,所以用大数JAVA
     * 至少有L个位置一样,就是L,L+1,L+2····m个位置一样。
     * 我们从反面来考虑,总数是n^m,我们求没有L个位置一样的数的概率
     * 设 dp[i][j]表示用前i个数,填充j个位置的方案数(要符合没有L个位置是一样的数)
     * dp[i][j]=dp[i-1][j]+Sigm( dp[i-1][j-k]*C[m-(j-k)][k]  ) k<=j&&k<L
     * 其实就是看第i个数,可以不填,填一个位置,两个位置······这样累加过来。
     * 那么最后的答案就是 (n^m-dp[1~n][m])/(n^m)
     */

    主要是大数比较麻烦。所以就用JAVA写了,当是练习下JAVA吧!

    /*
     * ZOJ 3380
     * 题目意思:有m个位置,每个位置填入一个数,数的范围是1~n,问至少有L个位置的数一样的概率
     * 输出要是最简分数的形式,所以用大数JAVA
     * 至少有L个位置一样,就是L,L+1,L+2····m个位置一样。
     * 我们从反面来考虑,总数是n^m,我们求没有L个位置一样的数的概率
     * 设 dp[i][j]表示用前i个数,填充j个位置的方案数(要符合没有L个位置是一样的数)
     * dp[i][j]=dp[i-1][j]+Sigm( dp[i-1][j-k]*C[m-(j-k)][k]  ) k<=j&&k<L
     * 其实就是看第i个数,可以不填,填一个位置,两个位置······这样累加过来。
     * 那么最后的答案就是 (n^m-dp[1~n][m])/(n^m)
     */
    import java.util.*;
    import java.io.*;
    import java.math.*;
    public class Main
    {
        static BigInteger[][] dp=new  BigInteger[110][110];
        static BigInteger[][] C=new BigInteger[110][110];//组合数
        public static void main(String arg[])
        {
            Scanner cin=new Scanner(new BufferedInputStream(System.in));
            for(int i=0;i<105;i++)
            {
                C[i][0]=C[i][i]=BigInteger.ONE;
                for(int j=1;j<i;j++)
                    C[i][j]=C[i-1][j-1].add(C[i-1][j]);
            }
            int N,M,L;
            while(cin.hasNext())
            {
                M=cin.nextInt();
                N=cin.nextInt();
                L=cin.nextInt();
                BigInteger tol=BigInteger.valueOf(N).pow(M);
                if(L>M)
                {
                    System.out.println("mukyu~");
                    continue;
                }
                if(L>M/2)//这个时候可以直接用组合数求出来
                {
                    BigInteger ans=BigInteger.ZERO;
                    for(int i=L;i<=M;i++)
                        ans=ans.add(C[M][i].multiply(BigInteger.valueOf(N-1).pow(M-i)));
                    ans=ans.multiply(BigInteger.valueOf(N));
                    BigInteger gcd=ans.gcd(tol);
                    System.out.println(ans.divide(gcd)+"/"+tol.divide(gcd));
                    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=1;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 ans=BigInteger.ZERO;
               for(int i=1;i<=N;i++)
                   ans=ans.add(dp[i][M]);    
               ans=tol.subtract(ans);
               BigInteger gcd=ans.gcd(tol);
               System.out.println(ans.divide(gcd)+"/"+tol.divide(gcd));
            }
        }
    }
    人一我百!人十我万!永不放弃~~~怀着自信的心,去追逐梦想
  • 相关阅读:
    PIC32MZ tutorial -- Core Timer
    PIC32MZ tutorial -- OC Interrupt
    PIC32MZ tutorial -- External Interrupt
    PIC32MZ tutorial -- Watchdog Timer
    PIC32MZ tutorial -- Output Compare
    PIC32MZ tutorial -- Input Capture
    PIC32MZ tutorial -- 32-bit Timer
    log | logstash
    Vxlan学习笔记——原理
    python——字符串格式化
  • 原文地址:https://www.cnblogs.com/kuangbin/p/2712980.html
Copyright © 2020-2023  润新知