题目描述:
有n层电梯,标记为整数1...n,现在处于第a层,第b层有秘密实验室不能进入(a != b).
现连续乘坐k轮电梯,若某次在x层,乘坐电梯后到达y层,则y满足 |x - y| < |x - b|,每到达一层记录层序号,k轮后即得到一个整数序列。求可能得到的不能序列数。
输入:
四个整数: n, a, b, k (2 ≤ n ≤ 5000, 1 ≤ k ≤ 5000, 1 ≤ a, b ≤ n, a ≠ b)
输出:
一个整数:不同序列数(mod 1000000007)
解题思路:
设 f[i][j]表示前i轮可能到达第j层的序列数。
设s[i][j]记录第i轮前j层可能达到序列总数,即s[i][j] = f[i][j]+s[i][j-1];
由题意知,可能到达第j层的层数x满足:
若j<b 则 x<(j+b)/2,即x<=(j+b-1)/2 且x!=j。f[i][j] = s[i-1][(j+b-1)/2]-f[i-1][j];
若j>b 则 x>(j+b)/2且x!=j。f[i][j] = s[i-1][n]-s[i-1][(j+b)/2]-f[i-1][j];
可知,s[k][n]即为所需解。
由于每次运算只需前一轮信息,故,f,g数组只用一维即可。
代码如下:
#include <stdio.h>
#define mod 1000000007
int n, a, b, k;
int f[5005] = { 0 }, s[5005] = { 0 };
int main()
{
scanf("%d%d%d%d", &n, &a, &b, &k);
f[a] = 1;
for (int i = 1; i <= n; i++) s[i] = s[i - 1] + f[i];
for (int i = 1; i <= k; i ++)
{
for (int j = 1; j <= n; j++)
{
if (j < b) f[j] = (s[(j + b - 1) / 2] - f[j] + mod ) % mod;
if (j > b) f[j] = ((s[n] - s[(j + b) / 2] + mod) % mod - f[j] + mod) % mod;
}
for (int j = 1; j <= n; j++) s[j] = (s[j - 1] + f[j]) % mod;
}
printf("%d\n", s[n]);
return 0;
}