CF479E Riding in a lift 题解

CF原题

题意

你正在一栋有 n ( n ≤ 5000 ) n(n\le 5000) n(n5000)层楼的大厦的第 a a a层,这栋楼里有一个秘密实验室在第 b b b层,你不能到达那一层楼。由于你闲得慌,所以决定做 k k k次电梯,每次到达一个楼层就在笔记本上的数列最后(初始的时候笔记本上没有数)写下当前的层数,请问 k ( k ≤ 5000 ) k(k\le 5000) k(k5000)次之后笔记本上写的数列有几种可能性?
每次坐电梯的时候为了避免到达第 b b b层,需满足:假设目前在第 k k k层,要前往第 j j j层,则 ∣ k − j ∣ < ∣ k − b ∣ |k-j|<|k-b| kj<kb

思路

朴素的DP

阶段性很明显,做一次电梯就是一个阶段,最容易想到的是 d p [ i ] [ j ] dp[i][j] dp[i][j]表示乘坐了 i i i次电梯,到了第 j j j层,有几种。使用push的更新方法比较符合正常逻辑,即用 d p [ i ] [ j ] dp[i][j] dp[i][j]去更新 d p [ i ] [ k ] ( 1 ≤ k ≤ n , ∣ j − k ∣ < ∣ j − b ∣ ) dp[i][k](1\le k \le n,|j-k|<|j-b|) dp[i][k](1kn,jk<jb)。这样空间上只要滚动数组即可,但时间上是 O ( n 2 k ) O(n^2k) O(n2k)

优化转移

由于本蒟蒻差分学得不好,只能前缀和,这个时候就要用当前位置 j j j推出是从第几层 ( k ) (k) (k)过来的。用题目中的式子经过一番 艰难的 推导,得到:
在这里插入图片描述
所以只要用 s u m sum sum存储第 i − 1 i-1 i1次坐电梯后的状态的前缀和,就可以直接得到 d p [ i ] [ j ] dp[i][j] dp[i][j]
注意: d p [ i ] [ j ] dp[i][j] dp[i][j]不能由 d p [ i − 1 ] [ j ] dp[i-1][j] dp[i1][j]转移过来,所以在程序中要减去 d p [ j ] dp[j] dp[j]

代码

如果不知道错哪里了的小伙伴可以看看彩蛋,说不定会有帮助。

#include<bits/stdc++.h>
using namespace std;
#define mod 1000000007
int n,a,b,k; 
long long dp[5005],sum[5005],ans;
int main(){
	cin>>n>>a>>b>>k;
	dp[a]=1;
	for(int i=a;i<=n;i++) sum[i]=1;
	for(int i=1;i<=k;i++){
		for(int j=1;j<b;j++) dp[j]=(sum[(b+j+1)/2-1]-dp[j]+mod)%mod;
		for(int j=b+1;j<=n;j++) dp[j]=(sum[n]-sum[(b+j)/2]-dp[j]+2*mod)%mod;
		for(int j=1;j<=n;j++) sum[j]=(sum[j-1]+dp[j])%mod;
	}                         
	for(int i=1;i<=n;i++) ans=(ans+dp[i])%mod;
	cout<<ans<<endl;
	return 0;
}

彩蛋

给大家讲个笑话,我第一遍写错是因为没有把式子倒过来,直接用满足 ∣ k − j ∣ < ∣ k − b ∣ |k-j|<|k-b| kj<kb j j j去转移 k k k j j j k k k完全反了。
第二遍是因为转移的时候做了减法,没有加上 m o d mod mod,变成负数了。
第三遍是因为我认为 ⌊ b + j 2 ⌋ \lfloor\frac{b+j}{2}\rfloor 2b+j在C++中应该写作 b + j − 1 2 \frac{b+j-1}{2} 2b+j1,因为上取整是 b + j + 1 2 \frac{b+j+1}{2} 2b+j+1嘛,其实是 b + j 2 \frac{b+j}{2} 2b+j
(自我诊断可能是因为刚退烧,脑子不太正常)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值