博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Uva 10328 逆向思维
阅读量:6392 次
发布时间:2019-06-23

本文共 2120 字,大约阅读时间需要 7 分钟。

传送门:

这个自己想的思路不知道哪里WA了,测试的都对,找不到数据。然后看了别人的思路感觉很棒棒啊。

题意:给你一个硬币,抛掷n次,问出现连续至少k个正面向上的情况有多少种。

原题中问出现连续至少k个H的情况,很难下手。我们可以试着将问题转化一下。

设dp[i][j]表示抛掷i个硬币出现连续至多j个H的情况种数。

因为是至多,所以j的值是可以大于i的,比如投5次,至多出现8个连续的情况,因为是递推,我们只考虑这个状态是怎么从前一个状态转移过来的

实际上原题中的出现连续至少k个H,即出现连续k个H,k+1个H,...n个H的并集,等价于dp[n][n]-dp[n][k-1],即从连续至多n个H的情况(其实这就是所有的抛掷情况种数)减去连续至多(k-1)个H的情况,这保证得到的所有情况一定至少有k个连续的H。

现在问题就变成了怎么求dp[i][j]。

考虑当i<=j的时候,dp[i][j]=dp[i-1][j]*2,即从上一阶段得到的抛掷序列后面增加正和反两种情况,如果出现连续的H个数大于j个,这种情况是非法的,但很显然此时不会出现这种情况。

当i>j时,如果继续用dp[i][j]=dp[i-1][j]*2就不行了。因为如果 从i-j到第i-1全部都是H ,那么这时候在第i个位置再加一个H,就会出现连续的H个数大于j个的非法状态,所以我们需要减掉 从i-j到第i-1全部都是H 的这种情况。那么这种情况有多少种呢。我们考虑该状态是如何转移而来的。试想第i-j-1个位置应该是什么呢。很明显应该是F。如果是H那就会出现非法状态了。那在第i-j-1之前的位置呢。无论H和F都可以,只要不出现连续的H个数大于j的非法状态即可,这就是dp[i-j-2][j]。

那么这样,dp[i][j]=dp[i-1][j]*2-dp[i-j-2][j]。

但这还是不够的。我们之前的推导都是基于第i-j-1个位置一定存在的前提下(i>j不能保证第i-j-1个位置一定存在),那如果第i-j-1个位置不存在,第i-j-2个位置也就不存在,上述方程也就不成立了。但这种情况很好想,此时一定是i==j+1,从第1个位置到第j个位置全部都是H,只有这一种情况,所以方程变成dp[i][j]=dp[i-1][j]*2-1。

综上:

dp[i][j]表示抛掷i个硬币出现连续至多j个H的情况种数

dp[0][j]=1

i<=j:dp[i][j]=dp[i-1][j]*2

i>j :i==j+1:dp[i][j]=dp[i-1][j]*2-1

      else: dp[i][j]=dp[i-1][j]*2-dp[i-j-2][j]

ans=dp[n][n]-dp[n][k-1]

 

因为是2的指数级可以达到100,所以要大数处理:

import java.util.*;import java.io.*;import java.math.*;public class Main{    public static void main(String[] args)    {        BigInteger[][] dp = new BigInteger[105][105];        for(int i=0; i<105; ++i)        {            dp[0][i]=new BigInteger("1");            for(int j=1; j<105; ++j)            {                dp[j][i]=new BigInteger("0");                if(j<=i)                     dp[j][i]=dp[j-1][i].multiply(BigInteger.valueOf(2));                else if(j==i+1)                     dp[j][i]=dp[j-1][i].multiply(BigInteger.valueOf(2)).subtract(BigInteger.valueOf(1));                else                     dp[j][i]=dp[j-1][i].add(dp[j-1][i].subtract(dp[j-i-2][i]));            }        }        Scanner in = new Scanner(System.in);        while(in.hasNextInt())        {            int a=in.nextInt(),b=in.nextInt();            System.out.println(dp[a][a].subtract(dp[a][b-1]));        }    }}

 

转载于:https://www.cnblogs.com/zhangmingzhao/p/7211571.html

你可能感兴趣的文章
ARM QT实现多点触摸【转】
查看>>
Weblogic项目部署教程
查看>>
Gradle -- buildScript块与allprojects块及根级别的repositories区别
查看>>
远程SSH连接服务与基本排错
查看>>
Objective-C学习笔记(十九)——对象方法和类方法的相互调用
查看>>
win10 WmiPrvSE.exe WMI Provider 占用CPU过高的问题
查看>>
hdu 4945 2048(DP)
查看>>
论文阅读:CNN-RNN: A Unified Framework for Multi-label Image Classification
查看>>
开篇有益-解析微软微服务架构eShopOnContainers(一)
查看>>
IE新发现
查看>>
quick check
查看>>
Debug时含有的子元素,在代码里获取不到的问题
查看>>
UVA 11020 - Efficient Solutions(set)
查看>>
RStudio版本号管理 整合Git
查看>>
使用 PHPMailer 发送邮件
查看>>
文件系统管理 之 Linux 创建文件系统及挂载文件系统流程详解
查看>>
CSS选择器学习小结
查看>>
什么叫贸工技发展模式?什么叫技工贸发展模式?
查看>>
MyEclipse for Spring 10.0: GWT 2.1 and Spring Scaffolding
查看>>
水木-搜索引擎技术版
查看>>