MWinter的博客

胧兮汒汒,暾兮昉昉,恻惐劻勷,吾心烺烺,巇崄沆漭,邅途兮何妨,吾道自爌炾。
扩大
缩小

【题解】dp的一种思路,突然想到的;兔子繁殖题解

兔子繁殖
假设有一对兔子在第1个月出生。刚出生的兔子年龄为0,每过一个月,免子年龄增加1。例如,在第
1个月出生的免子,在第1个月年龄为0,在第2个月年龄为1,等等。
免子具有繁殖能力。一对兔子从年龄达到k开始,每t个月会生出一对免子。同时兔子具有一定的寿
命,每对兔子在累计生出m对兔子之后死亡。也就是说,一对兔子在年龄为
k,k+t,k+2t,·.,k+(m-1)t的月份各生出一对免子,在年龄为k+(m-1)t的月份死亡
请你计算出在第n个月,有多少只未死亡的兔子
输入格式
从标准输入读入数据
输入共一行,包含四个正整数n,k,t,m。保证1<k,tm<n<10
输出格式
输出到标准输出
输出一行,包含一个整数,表示第n个月未死亡的兔子数量。由于答案可能很大,你只需输出答案除以
10007的余数即可
样例一
input
5 2 1 3 
output

4

explanation
第1个月,有1对免子,年龄为0
第2个月,有1对免子,年龄为1
第3个月,有2对免子,年龄分别为2,0,其中年龄为0的免子是年龄为2的免子生的。
第4个月,有3对免子,年龄分别为3,1,0,其中年龄为0的免子是年龄为3的免子生的
第5个月,有4对兔子,年龄分别为2.1.0.0,注意上个月年龄分别为3.1的两只兔子在这个月年
分别为4,2,各生出一对免子,但年龄为4的兔子已死亡
因此第5个月有4对未死亡的兔子
样例二
input

1000 23 11 7
output

5992

各位可以先思考一下;

这道题最开始想出来的代码大致是这样的:

循环(1~总月数,i){
	循环(0~繁殖总次数,j){
      新出生的[j*繁殖周期+成年时间]+=新出生的[i]; }//步长为繁殖频率的区间修改 如果(繁殖总次数*繁殖周期+成年时间<=总月数) 答案-=1; }

这时候我们绝对明白,肯定是过不了的,O(n*m)的数据规模太大了,承受不了;
所以这时候我们肯定想到了常见的dp优化,比如说转化为背包,斜率优化,之类的,但很明显都是出不来的;
这时候我们眼前所剩的路其实不多了;
我们最后发现, 诶! 这个m所在的循环有没有一点像是一个区间修改;
但是好像和我们常见的区间修改不太一样;
因为他有一个 “繁殖周期” 在里面搞鬼,不让我们用 差分和区间和 ;
那么,这时候但凡 “繁殖周期” 是1那就好了;
稍微思考一下,这种情况下代码大概是这样的:
循环(1~总月数,i){
  新出生的[i]=上次出生的-现在死的+现在新成年的
}
然后咱们用 新出生的 这个数组来表示一下这三个变量;
循环(1~总月数,i){
  新出生的[i]=新出生的[i-1]-新出生的[i-繁殖周期*繁殖总次数+成年时间]+新出生的[i-成年时间]
}
然后就发现,这其实是的可以动态维护的 差分和区间和;
诶,就发现,好像这个差分看似是 不连续的 ,但其实差的分都是刚好一定在上一个数;
所以这道题就告诉我们;
有些题看似很难,但其实 一步一步 按照 思路 来推理,好像就没有那么难了;
(P.S.:如果是确实是有步长的 差分和区间和 的话,那么可以用一个二维数组来维护,因为你会发现一个步长中的每个数所代表的数组都是互不干扰的)
所以这道题就基本上打开了我对于dp的思路,之前的话就是一直dp要想很久;
posted @ 2023-02-11 01:27  MingWinter  阅读(72)  评论(0)    收藏  举报