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 <string>

using namespace std;

#define MP make_pair
#define PB push_back
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
typedef long long LL;
typedef unsigned long long ULL;
typedef vector<int> VI;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
const int INF = INT_MAX / 3;
const double eps = 1e-8;
const double DINF = 1e60;
const int maxn = 5005;
const LL mod = 1e9 + 7;
int n, a, b, k;
int f[maxn][maxn], sum[maxn][maxn];
int lbd[maxn], rbd[maxn];

int mabs(int x) {
    return x < 0 ? -x : x;
}

int main() {
    cin >> n >> a >> b >> k;
    for(int i = 1; i <= n; i++) {
        lbd[i] = INF; rbd[i] = -INF;
    }
    for(int i = 1; i <= n; i++) {
        for(int j = 1; j <= n; j++) {
            if(mabs(j - i) < mabs(j - b)) {
                lbd[i] = min(lbd[i], j);
                rbd[i] = max(rbd[i], j);
            }
        }
    }
    lbd[b] = rbd[b] = b;
    f[0][a] = 1;
    for(int i = 1; i <= n; i++) sum[0][i] = sum[0][i - 1] + f[0][i];
    for(int i = 1; i <= k; i++) {
        for(int j = 1; j <= n; j++) {
            int l = lbd[j], r = rbd[j];
            f[i][j] = (sum[i - 1][r] - sum[i - 1][l - 1] + mod) % mod;
            if(lbd[j] <= j && rbd[j] >= j)
                f[i][j] = (f[i][j] - f[i - 1][j] + mod) % mod;
        }
        for(int j = 1; j <= n; j++)
            sum[i][j] = (sum[i][j - 1] + f[i][j]) % mod;
    }
    cout << sum[k][n] << endl;
    return 0;
}
时间: 2024-11-09 11:07:15

CF R274 Div2 E 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 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)的二元组都保存下来.这样处理

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.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[

CF #261 div2 D. Pashmak and Parmida&amp;#39;s problem (树状数组版)

Parmida is a clever girl and she wants to participate in Olympiads this year. Of course she wants her partner to be clever too (although he's not)! Parmida has prepared the following test problem for Pashmak. There is a sequence a that consists of n

CF #261 DIV2 A,B,C,D

A 先判断邻边长度是否相等,不是就无法构成正方形,否则的话位置坐标搞一下 #include <iostream> #include <cstdio> #include <cstring> #include <string> #include <cmath> #include <algorithm> #include <bitset> #include <vector> #include <set>

CF#215 DIV2: B. Sereja and Suffixes

Sereja has an array a, consisting of n integers a1, a2, ..., an. The boy cannot sit and do nothing, he decided to study an array. Sereja took a piece of paper and wrote out m integers l1,?l2,?...,?lm (1?≤?li?≤?n). For each number li he wants to know

cf#261 div2 解题报告

.....代码没什么可说的,主要是学习各路大神姿势 A题 化简化简水题,都告诉平行坐标轴了,数据还出了对角线,后面两个点坐标给的范围也不错 ........和最优代码相比姿势有点混乱 #include <cstdio> int x[4],y[4]; int abs(int n){ return n<0?-n:n; } int main(){ scanf("%d%d%d%d",x,y,x+1,y+1); int dx=abs(x[0]-x[1]); int dy=abs

【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\) 个弹珠,最后一个固定的弹