输入 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;
}