timus 1513. Lemon Tale URAL 解题报告

timus   1513. Lemon Tale    URAL 解题报告

题目大意:就是一行字符,LB组成,一个检测员呢和L有仇啊,只要是多余K个连续的L出现,那么这条语句就不合法,为此,三名程序猿很关心这个软件里面的这天信息,连忙修改,把相应的字符L换成B; 这个问题给字符串长度n还有k;问有多少种组合情况!
这个题乍一看以为和组合数学有关,但是这是在DP分组里啊,肯定用DP能做啊,琢磨了半天,想到了一个二维数组的DP[i][j]   ,  表示当前位就是i位是j(j有两种状态)的合法状态的数目,和前面多少多少位有关! 为了避免计数混乱,dp[i][B]=dp[i-k-1][B]+dp[i-k][B]+dp[i-k+1][B]+……+dp[i][i-1];      当i从i-k-1转化过来的时候,中间的全是L字符,然后从i-k转化过来的时候中间也全是L字符,这样避免计数混乱!   然后dp[i][L] ……
想到这里很兴奋,终于找到方法了,DP自己感觉掌握的不错了,没想到实现的时候出了各种各样的问题,首先,需要高精度啊!  这种组合的情况一看数目肯定很大啊!
c++高精度太费事了,不想写,于是就换做java的高精度,写了一个二维数组的O(n*k)的算法,果断超时,当时还想来电小优化,认为二维数组 的大数超时,一维的可能就好了……
但是仍然超时,其实自己找一组数据测测就知道了吗,哎!       后来在一维数组的基础之上慢慢改,一直出现各中小错误,各种调试,其实是自己还没有想明白,想清楚的缘故!
后来思路清晰了:
dp[i]表示第i位合法状态下的L和B字符总共的状态数,那么他由dp[i-1]位转移过来,但是dp[i-1]可能是由dp[i-2]……  假设前面的k位已经恰好有连续的k个L了,那就惨了,所以得减去一些;    刚开始调试的过程中没有想清楚,写多了,把前K+1位已经有K+1个L字符,当前即使是B字符也不合法的状态也算上了,肯定得减去啊,所以一不小心减多了……
后来才明白前面是合法状态数肯定不能出现K+1位的L啊! 所以只要当前位时B,肯定合法,只要k不是0!

然后dp[i]既然表示第i位时BL两种字符的总数,那么如果只要求算该位B字符的怎么办啊,就是dp[i-1就好了,在i-1位的基础上加上i位的B就好了嘛(好好琢磨琢磨)!
但是第i为只是B的状态数依赖于i-1,但是如果i=1呢? i=1肯定是有状态的,但是大以来i-1位啊,所以在处理边界条件的时候需要注意,为了满足他的特殊需求啊,就得特殊定义啊,有的时候特殊定义不好,会导致出错,但有的时候特殊定义可以满足题目要求啊!

如果这个题还有什么坑的话,那我不得不说是k=0的时候了,或者还有n=1的时候,特殊情况特殊处理嘛!

总结一下这次的DP,一定要搞清楚状态,不要盲目的写,虽然有的时候没思路写着写着就有了,但是如果写着写着出现了各种各样的……  那就不得不不停下来好好想想了!
关于边界的处理,边界处理时为了满足题目的,有的时候第0位没有可能出现,但是为了满足题目转化的需求,要根据实际状况去做出处理!

上代码:  如果还有什么需要说明的就是URAL的java测评不限制Main,你也可以改成其他名字,但是 不要有中文的注释语句,反之会报错啊!
import java.io.*;
import java.math.BigInteger;
import java.util.*;

public class Main4 {
   
	static int N=10010;
    static BigInteger dp[]=new BigInteger[N];
    static int n,k;
    public static void main(String[] args) throws IOException  {
        Scanner sc = new Scanner(System.in);
         ///现在二维已经压缩到一维了,但是还是超时了;看来光压缩空间还不管用,还得将时间优化下
        ///当然这个题用二维还是比较好想的,当初以为二维会超时,因为高精度可能比较费时间,所以没敢做
        ///优化到1维,然后又从O(n*k)优化到O(n)  再然后处理掉各种各样的边界
        ///主要思路是dp[i]表示第i位合法状态下的L,B字符的状态;记住是合法的,再加一位从改为转化过来
        ///新加的这一位
         n = sc.nextInt();
         k=sc.nextInt();
         BigInteger big2=BigInteger.valueOf(2);
     	
         if(n==1){
         	if(k==1)
         	System.out.println(2);
         	else System.out.println(1);
         	return ;
         } else if(k==0){
        	 System.out.println(1);return ;
         }
         
         for (int i = 0; i <n+1; i++) {
             dp[i] = BigInteger.ZERO;
         }
     	
     	dp[0]=BigInteger.ONE;
     	for (int i = 1; i <=k; i++) {
             dp[i] =dp[i-1].multiply(big2) ;
            // System.out.println(i+" "+dp[i]);
         }
         
     	//dp[0]=BigInteger.ZERO;
       
         for(int i=k+1;i<=n;++i){
        	 dp[i]=dp[i].add( dp[i-1].multiply(big2) );
        	// dp[i]=dp[i].subtract(dp[i-k-1]);
        	 if(i-k-2>=0)dp[i]=dp[i].subtract(dp[i-k-2]);
        	 else if(i-k-1==0)dp[i]=dp[i].subtract(BigInteger.ONE);
        	 ///注意特殊边界的处理情况,因为这里实际i-k-2视为了i-k服务的,所以i-k-2超了范围也要特殊处理
         	 //System.out.println(i+" "+dp[i]);
         }
 
             System.out.println(dp[n]);
    }
   
}

 

1513. Lemon Tale

Time limit: 1.0 second
Memory limit: 64 MB

Background

For each programmer a point comes when the last contest is lost, and it is time to retire. Even Three Programmers themselves could not escape the common lot. But the Programmers also wanted to keep a good memory about themselves. For this noble purpose they created problems and organized extremely popular programming contests from time to time. Of course, this work was not well paid, but for true programmers a glory was more important than money.
However it is only the first half of a job to think out a brilliant problem. The second one is to create a politically correct statement for it.

Problem

The matter is the statement of some problem for the upcoming contest was written by the Third Programmer, who knew nothing about political correctness. He just wrote a story about citrus plants growing. As a result a word "lemon" was mentioned  N times in the statement.
Besides, the problem is to be looked through by famous censor Alexander K. right before the contest. And it is a known fact, that lemons remind him of oranges he hates furiously. It worries the First and the Second Programmers greatly - they know exactly, that if a word "lemon" occurs more than  Ktimes successively, the problem will be immediately disqualified from the contest.
That is why the First and the Second Programmers connived secretly to login to the server at the eve of the contest and replace some "lemons" with much more politically correct "bananas" so that the problem could not be disqualified. How many ways are there to do it?

Input

The only line contains the integer numbers  N (1 ≤  N ≤ 10000) and  K (0 ≤  K ≤  N).

Output

You should output the desired number of ways.

Sample

input output
5 2
24

Hint

Let us denote a word "lemon" by a letter "L" and a word "banana" by a letter "B". So in the sample the initial sequence of words "LLLLL" might be transformed into the following politically correct sequences: "LLBLL", "LLBLB", "LLBBL", "LLBBB", "LBLLB", "LBLBL", "LBLBB", "LBBLL", "LBBLB", "LBBBL", "LBBBB", "BLLBL", "BLLBB", "BLBLL", "BLBLB", "BLBBL", "BLBBB", "BBLLB", "BBLBL", "BBLBB", "BBBLL", "BBBLB", "BBBBL" and "BBBBB".

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值