输入 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; }
时间: 2024-11-14 21:55:03