您的位置:首页 > 其它

繁华模拟赛 Vicent坐电梯

2016-09-24 23:17 232 查看




/*
n<=5000
­这样就不能用O(n)的转移了,而是要用O(1)
的转移。
­注意我们每次的转移都来自一个连续的区间,
而且我们是求和
­区间求和?
­前缀和!
­令sum[step][i]表示f[step][1~i]的和
­还是以B下侧为例
­ f[step][i]=sum[step-1][i-1]+sum[step-1][k]-sum[step-1][i]

*/
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;

typedef long long ll;
const int MAXN = 6000;
const int MOD  = 1000000007;
int f[MAXN][MAXN] = {{0}};
int n, a, b, k;

inline int getnum()
{
char c; int ans = 0; bool flag = false;
while ((c = getchar()) == ' ' || c == '\r' || c == '\n');
if (c == '-') flag = true; else ans = c - '0';
while ((c = getchar()) >= '0' && c <= '9') ans = ans * 10 + c - '0';
return ans * (flag ? -1 : 1);
}

inline void add(int &a, int b)
{
ll tmp = (ll)a + b;
if (tmp >= MOD) a = (int)(tmp - MOD);
else if (tmp < 0) a = (int)(tmp + MOD);
else a = (int)tmp;
}

int main()
{
freopen("lift.in", "r", stdin);
freopen("lift.out", "w", stdout);
n = getnum(); a = getnum(); b = getnum(); k = getnum();
if (fabs(a - b) - 1 == 0) { printf("0\n"); return 0; }
for (int i = a; i <= n; i++)
f[0][i] = 1;
for (int step = 1; step <= k; step++)
for (int i = 1; i <= n; i++)
if (i == b) f[step][i] = f[step][i - 1];
else
{
f[step][i] = f[step][i - 1];
if (i < b)
{
int x = (b + i) / 2;
if ((b + i) % 2 == 0) x--;
add(f[step][i], f[step - 1][x]);
add(f[step][i], -f[step - 1][i]);
add(f[step][i], f[step - 1][i - 1]);
}
else
{
int x = (b + i) / 2;
add(f[step][i], f[step - 1]
);
add(f[step][i], -f[step - 1][x]);
add(f[step][i], -f[step - 1][i]);
add(f[step][i], f[step - 1][i - 1]);
}
}
printf("%d\n", f[k]
);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: