HDU4624Endless Spin(clj计数ppt)

链接:http://acm.hdu.edu.cn/showproblem.php?pid=4624
题意:总共有n个球,每次随机选择一段区间染黑(每段区间被选择的概率相同),求期望多少次所有球都被染黑。

分析:虽然ppt中说显然,但我认为这个问题最为精妙的地方就在第一步:

=i=1p[i]
,其中 p[i] 为i次之后仍然存在白球的概率。
这个公式怎么来的呢?直观的理解就是假如当前还有白球,那么必然还要染一次,而这一次对整体期望的贡献就是p[i].这之后就是传统的处理方法,枚举哪些球是白球,那么可以染黑的区间是固定的,由于这当中会有重复计算,只需要把奇数个白球的情况减去偶数个白球的方案数就是总的方案数,这种容斥方法在后面的Substring Pairs一题中也有体现。
另外,这题要保留15位小数,要用java才能通过。
java进行文件读写,可以使用Printwriter来做写操作,不过要记得close.
java可以方便的使用printf;
java的BigDecimal进行divide操作时,要设置scale和舍入mode

附上java代码

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
public class Main
{
        public static void main(String[] args) throws FileNotFoundException 
        {
            File fp2=new File("/home/poursoul/J.out");
            PrintWriter cout=new PrintWriter(fp2);
            Long [][][]dp=new Long[55][2500][2];
            BigDecimal []rep=new BigDecimal[100];
            for(int i=0;i<60;i++)rep[i]=new BigDecimal("0");
            for(int i=0;i<55;i++)for(int j=0;j<2500;j++)for(int k=0;k<2;k++)dp[i][j][k]=new Long(0);
            dp[0][0][0]=(long)1;
            BigDecimal t1=new BigDecimal("1");

            for(int i=1;i<=51;i++)
            {
                for(int j=0;j<i*(i-1)/2;j++)
                {
                    for(int k=0;k<2;k++)
                    {
                        for(int ni=0;ni<i;ni++)
                        {
                            int tot=i-ni-1;
                            tot=tot*(tot+1)/2;
                            if(j>=tot)
                               dp[i][j][k]+=dp[ni][j-tot][k^1];
                        }
                    }
                    Long tp=(long)i*(i-1)/2;
                    BigDecimal p=new BigDecimal(j).divide(new BigDecimal(tp.toString()), 50, BigDecimal.ROUND_HALF_UP);
                    Long tp2=dp[i][j][1]-dp[i][j][0];
                    rep[i-1]=rep[i-1].add(t1.divide(t1.subtract(p), 50, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(tp2.toString())));
                }
               dp[i][i*(i-1)/2][0]=new Long(1);
            }
            for(int n=1;n<=50;n++)
                cout.printf("\"%.15f\",\n",rep[n]);
            cout.close();
        }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值