LightOJ 1064 Throwing Dice 概率DP

题目大意:

就是问投骰子n次, 得到的点数和不小于x的概率 骰子6个面点数分别为1,2,3,4,5,6,出现几率一样


大致思路:

就是一个简单的计数问题, 转台转移方程见代码注释

由于涉及到大数,为了方便写的Java


代码如下:

Result  :  Accepted     Memory  :  23824 KB     Time  :  296 ms

/*
 * Author Gatevin
 * Created Time : 2014/12/24 20:21:54
 * File Name: Sora_Kasugano.java
 */
import java.util.Scanner;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.Map;
import java.util.HashMap;
import java.util.Queue;
import java.util.LinkedList;
import java.io.FileOutputStream;

/*
 * 很简单的一个dp计数问题
 * 如果用dp[i][j]表示在投掷i次之后点数和为j的方案数
 * 那么dp[i][j] = ∑dp[i - 1][j - k] (1 <= k <= min(6, j))
 * 初始dp[0][0]这样得到所有的投掷n次点数为m的方案数
 * 直接求和即可得到满足题意的方案, 约分一下就行了
 */

//submit前写的"public class Sora_Kasugano" CompilationError了一发..
public class Main{
    public static void main(String args[]){
        int t, n, x;
        BigInteger dp[][] = new BigInteger[26][160];
        for(int i = 1; i <= 150; i++) dp[0][i] = BigInteger.ZERO;
        dp[0][0] = BigInteger.ONE;
        for(int i = 1; i <= 25; i++)
        {
            for(int j = 0; j < i; j++) dp[i][j] = BigInteger.ZERO;
            for(int j = i; j <= 6*i; j++)
            {
                dp[i][j] = BigInteger.ZERO;
                for(int k = 1; k <= 6; k++)
                    if(j >= k)
                        dp[i][j] = dp[i][j].add(dp[i - 1][j - k]);
            }
            for(int j = 6*i + 1; j <= 150; j++) dp[i][j] = BigInteger.ZERO;
        }
        Scanner cin = new Scanner(System.in);
        t = cin.nextInt();
        for(int cas = 1; cas <= t; cas++)
        {
            n = cin.nextInt();
            x = cin.nextInt();
            BigInteger dem = BigInteger.valueOf(6).pow(n);
            BigInteger num = BigInteger.ZERO;
            for(int i = x; i <= 6*n; i++)
                num = num.add(dp[n][i]);
            BigInteger gcd = dem.gcd(num);
            dem = dem.divide(gcd);
            num = num.divide(gcd);
            if(dem.compareTo(BigInteger.ONE) != 0)
                System.out.println("Case " + cas + ": " + num + "/" + dem);
            else
                System.out.println("Case " + cas + ": " + num);
        }
    }
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值