首页 > 代码库 > 繁华模拟赛 Vicent坐电梯

繁华模拟赛 Vicent坐电梯

技术分享

技术分享


/*
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][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\n", f[k][n]);}

 

繁华模拟赛 Vicent坐电梯