CF 479E Riding in a Lift 前缀和 DP

输入 n a b k 有n层楼 起点在a层 b层是不能到达的 假设当前在x层 每一次可以到达y层 满足 |x-y| < |x-b| 求进行k次的不同方案数

dp[i][j]为第i次到达j层的方案数 dp[i][j] = sum(dp[i-1][k])  其中|k-j| < |k-b|

满足条件的k是连续的一段 用前缀和优化

#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;
typedef long long LL;
const int maxn = 5010;
const int mod = 1000000007;
LL dp[maxn][maxn];
int main()
{
	int n, a, b, m;
	while(scanf("%d %d %d %d", &n, &a, &b, &m) != EOF)
	{
		memset(dp, 0, sizeof(dp));
		for(int i = a; i <= n; i++)
			dp[0][i] = 1;
		for(int i = 1; i <= m; i++)
		{
			for(int j = 1; j <= n; j++)
			{
				if(j == b)
				{
					dp[i][j] += dp[i][j-1];
					continue;
				}
				if(j < b)
				{
					int d = b-j;
					int x = j+(b-j-1)/2;
					dp[i][j] += dp[i-1][x]-(dp[i-1][j]-dp[i-1][j-1]);
					dp[i][j] %= mod;
				}
				else
				{
					int d = j-b;
					int x = j-(j-b-1)/2;
					dp[i][j] += dp[i-1][n]-dp[i-1][x-1]-(dp[i-1][j]-dp[i-1][j-1]);
				}
				dp[i][j] += dp[i][j-1];
				dp[i][j] %= mod;
			}
		}
		//for(int j = 1; j <= n; j++)
		printf("%I64d\n", (dp[m][n]+mod)%mod);
	}
	return 0;
}
时间: 2024-11-14 21:55:03

CF 479E Riding in a Lift 前缀和 DP的相关文章

Codeforces 479E Riding in a Lift(dp)

题目链接:Codeforces 479E Riding in a Lift 题目大意:有一栋高N层的楼,有个无聊的人在A层,他喜欢玩电梯,每次会做电梯到另外一层.但是这栋楼里有个秘 密实验室在B层,所以每次他移动的时候就有了一个限制,x为当前所在层,y为目标层,|x - y| < |x - b|.问说移动K次 后,有多少不同的路径. 解题思路:dp[i][j]表示在第i步到达j层有多少种不同的路径,dis = abs(j-B) - 1,那么在[j-dis,j+dis]这个范围都能被转 移,除了j

Codeforces 479E Riding in a Lift:前缀和/差分优化dp

题目链接:http://codeforces.com/problemset/problem/479/E 题意: 有一栋n层的房子. 还有一个无聊的人在玩电梯,每次玩电梯都会从某一层坐到另外一层. 他初始在a层,然后要玩k次电梯. 这栋楼里还有一个神秘实验室,在b层. 这让他每次坐电梯受到了限制: 当前在x层,然后要坐到y层,则必须满足|x-y|<|x-b| 问你共有多少种坐电梯的方案. 题解: 表示状态: dp[i][j] = numbers 表示当前在第i层,已经坐了j次电梯,此时的方案数.

CodeForces 479E Riding in a Lift

题意:给你一个n层楼的电梯,起始楼层为a,有一个楼层b永远都不能访问.假设你现在所在的楼层为 x ,目标楼层为y,y必须满足条件|x-y| < |x -b| 解题思路:时间复杂度是k×nxn,但是我们知道每次更新先把它存起来,然后到下一层再直接更新就行了,这里就需要用到前缀和.还要注意 mod 数加负数. 解题代码: 1 // File Name: 479e.cpp 2 // Author: darkdream 3 // Created Time: 2015年03月08日 星期日 21时37分1

【CF】38E Let&#39;s Go Rolling! (dp)

前言 这题还是有点意思的. 题意: 给你 \(n\) (\(n<=3000\)) 个弹珠,它们位于数轴上.给你弹珠的坐标 \(x_i\) 在弹珠 \(i\) 上面花费 \(C_i\) 的钱 可以使弹珠在原地不动 (\(-10^9<=x_i,C_i<=10^9\)),游戏开始时,所有的弹珠向左滚动,直到碰到定在原地不动的弹珠,其花费是其滚动的距离.总花费=开始前的花费+弹珠滚动的花费,问最小的花费是多少 题解 首先划分出阶段,,我们可以先将弹珠排序,前 \(i\) 个弹珠,最后一个固定的弹

Codeforces Round #274 (Div. 2) E:Riding in a Lift DP + 前缀优化

题意: n,a,b,k(2?≤?n?≤?5000,1?≤?k?≤?5000,1?≤?a,?b?≤?n,a?≠?b).四个数.1到n的数,顺序排列,其实位置人在a位置而中心位置在b,人每次只能走一个点走动的距离必须小于|b?a|,人走k步之后停止,问人一共有多少种走法. 分析: 开始很容易想到一个深度优先搜索实现递归方法dfs(a, k)但k变为0就到达搜索底部,这样时间复杂度是O(nk)显然非常不好. 然后可以想到会有重算的情况,就可以加一个记忆优化把算过的(a,k)的二元组都保存下来.这样处理

CF R274 Div2 E Riding in a Lift DP

先预处理出能到当前点的区间,然后通过前缀和求得当前值即可. #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <stack> #include <map> #include <set> #include <climits> #include <iostream> #include &

Codeforces 480C Riding in a Lift dp

题目链接:点击打开链接 题意: 给定 n a b k 构造一个长度为k的序列. 使得序列中 对于任意两个相邻的数 | w[i-1] - w[i] | < | w[i] - b | 且第一个数 |a - w[1] | < | w[1] - b | 问: 有多少种不同的序列. 思路:dp 对于粗暴的dp复杂度是 n^3 我们可以用前缀和来优化掉一维的dp.. 反正是简单粗暴的题.具体看代码吧.. #include <cstdio> #include <iostream> #

Codeforces Round #274 (Div. 2) E. Riding in a Lift(DP)

Imagine that you are in a building that has exactly n floors. You can move between the floors in a lift. Let's number the floors from bottom to top with integers from 1 to n. Now you're on the floor number a. You are very bored, so you want to take t

Codeforces Round #274 Div.1 C Riding in a Lift --DP

题意:给定n个楼层,初始在a层,b层不可停留,每次选一个楼层x,当|x-now| < |x-b| 且 x != now 时可达(now表示当前位置),此时记录下x到序列中,走k步,最后问有多少种可能的数的序列. 解法: 定义:      dp[i][j] 表示第i步在j楼的不同序列的个数 转移方程: 当j<b时, 那么dp[i][j] += dp[i-1][0~(j与b的中点(以下))] 当j>b时, 那么dp[i][j] += dp[i-1][(j与b的中点(以下))~n] 由于dp[