UVA_10328
这个和之前做过的一个计算连续胜利场数为k场的概率的题目很像,所以就把那个题目用到的思想搬过来了。
我们设f[i][j]表示抛第i个硬币时连续的H不超过j个的情况总数,那么由于第i个可以为正可以为负,因此不妨先写成f[i][j]=2*f[i-1][j]。
但是这么写有些情况下是不正确的,什么情况呢?就是前面i-1个硬币的最后j个全是H,那么第i个如果再是H的话,总长度就变成j+1了。
在减去这部分的种数的时候,我们要分情况讨论一下。如果i==j+1,那么就只有一种情况可以出现j+1个H,就是i个硬币全部是H,因此减去1即可。如果i>j+1,那么如果第i个硬币前面有j个H的话,那么第i-j-1个硬币必然应该是T,否则H的连续的数量就会超过j,这种情况就不可能包含在f[i-1][j]里面了,因此,我们这时只要减去一个f[i-j-2][j]即可。
最后结果显然应该是输出f[n][n]-f[n][k-1]。
import java.math.BigInteger;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
BigInteger[][] f = new BigInteger[110][110];
for(int i = 0; i <= 100; i ++)
f[0][i] = new BigInteger("1");
f[1][0] = new BigInteger("1");
for(int i = 1; i <= 100; i ++)
f[1][i] = new BigInteger("2");
for(int i = 2; i <= 100; i ++)
for(int j = 0; j <= 100; j ++)
{
f[i][j] = f[i - 1][j].multiply(BigInteger.valueOf(2));
if(i == j + 1)
f[i][j] = f[i][j].add(BigInteger.valueOf(-1));
else if(i > j + 1)
f[i][j] = f[i][j].add(f[i - j - 2][j].negate());
}
while(cin.hasNext())
{
int n = cin.nextInt();
int k = cin.nextInt();
System.out.println(f[n][n].add(f[n][k - 1].negate()));
}
}
}