競技プログラミング日記

主に AtCoder の記事です

AtCoder Beginner Contest 253E

dp を累積和で高速化する.

\(dp_{i,j} := [0,i)\) まで,last \(j\) のときの答え
とする.
今を\(y \in M\),直前を \(x \in M\) とすると, 遷移は
\(dp_{i+1, y} += \sum_{x \in [l,r) } dp_{i,x} \)
となるので,累積和で高速化できる.

ABC253E

使っている記号,マクロ等 "https://ecsmtlir.hatenablog.com/entry/2022/12/23/131925"

int main() {
  ll n, m, k ;
  cin >> n >> m >> k;

  if(k == 0){
    cout << mint(m).pow(n).val() << endl;
    return 0;
  }
 

  vector<mint> dp(m);
  rep(j,m) dp[j] = 1;
 
  rep(i,n-1){
    vector<mint> old(m);
    swap(dp, old);
    vector<mint> s(m+1);
    rep(j,m) s[j+1] = s[j] + old[j];

    auto sum = [&](ll l, ll r) -> mint {
      if(l > r) return mint(0);
      return -s[l] + s[r];
    };
   
    rep(y,m){
      dp[y] += sum(0, min(m, y-k+1)) + sum(max(y+k,0LL), m);
    }
  }

  mint ans;
  rep(j,m) ans += dp[j];
  cout << ans.val() << endl;

  return 0;
}