source:
题意:进行n次掷硬币,求至少有k次连续出现正面的方案数。
思路:此题和之前写过一题极为类似:点击打开链接
均需要用到计数技巧:将至少化为至多之差,然后用递归dp。于是递推关系参照点击打开链接即可,再次特殊之处在于需要用到大数,而大数直接上java!
注:java好久不写又有些生疏了,注意定义时new的用法,加减乘除直接调用方法,标准输入输出cin的定义,用hasNextInt()判断EOF结束标准等等,务必时常写时常回顾!
代码如下:
import java.io.BufferedInputStream;
import java.math.BigInteger;
import java.util.Scanner;
public class Main
{
static int n;
public static BigInteger f(int u) throws Exception
{
BigInteger[][] dp = new BigInteger[105][2];
if(u>0) dp[0][0]=new BigInteger("1"); else dp[0][0]=new BigInteger("0");
dp[0][1]=new BigInteger("1");
for(int i=1;i<n;i++)
{
dp[i][1]=dp[i-1][0].add(dp[i-1][1]);
if(i<u) dp[i][0]=dp[i-1][0].add(dp[i-1][1]);
else if(i==u) dp[i][0]=dp[i-1][0].add(dp[i-1][1]).subtract(new BigInteger("1"));
else dp[i][0]=dp[i-1][0].add(dp[i-1][1]).subtract(dp[i-u-1][1]);
}
return dp[n-1][0].add(dp[n-1][1]);
}
public static void main(String[] args) throws Exception
{
// TODO Auto-generated method stub
Scanner cin = new Scanner(new BufferedInputStream(System.in));
while(cin.hasNextInt())
{
n=cin.nextInt();
int k=cin.nextInt();
System.out.println(f(n).subtract(f(k-1)));
}
}
}
其实还可进一步优化:可以预先算出100以内的所有结果,后面读入询问后直接输出!但这种每次调用方法的方式也不会超时。