![](https://images2015.cnblogs.com/blog/811498/201609/811498-20160924231243074-1057854199.png)
![](https://images2015.cnblogs.com/blog/811498/201609/811498-20160924231256074-1138426732.png)
/*
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 == '
' || c == '
');
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
"); 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][n]);
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
", f[k][n]);
}