Typical DP Contest F - 準急
解法
dp[i][j] := i 番目の電車まで考えた時,右端が j である (j=0: 停車, j=1: 通過) 場合の数
として更新していく.
右端で停車しない場合は単純に dp[i-1][0] + dp[i-1][1] でよい.
停車する場合は,直前の K-1 回で停車し,かつ駅 1 から駅 i-1 までだけを考えれば条件を満たす場合の数を引く必要がある.
これは dp[i-K][1] で求まる.(直前 K-1 回が停車駅なら,駅 i-K では通過していなければならない)
ソースコード
#include <bits/stdc++.h> using namespace std; using ll = long long; constexpr ll MOD = 1e9+7; int main() { int N, K; cin >> N >> K; vector<vector<ll>> dp(N+1, vector<ll>(2)); dp[0][0] = dp[0][1] = 1; for(int i=1; i<=N; ++i) { if(i == 1) { dp[1][0] = 1; dp[1][1] = 0; continue; } dp[i][1] = (dp[i-1][0] + dp[i-1][1]) % MOD; dp[i][0] = (dp[i-1][0] + dp[i-1][1]) % MOD; if(i - K >= 0) { dp[i][0] = (dp[i][0] - dp[i-K][1] + MOD) % MOD; } } cout << dp[N][0] << endl; }