
配点: 300 点 / 実行時間制限: 2 sec / メモリ制限: 1024 MB / Difficulty: ???
問題概要
正整数 が与えられる。長さ
の数列
の各要素の値を、以下の方法で定義する。
のとき、
のとき、
このとき、 を
で割った余りを求めよ。
制約
- 入力は全て整数。
考察
愚直に を求めるやり方だと、
のときに毎回
回の計算が発生することになり、全体の計算量は
となってしまう。
そこで、この部分の処理を累積和を使って高速化しよう。
今回は、 の値が求まった後に累積和テーブルが順次定まっていくことになる。
また、本問では の大小関係には触れられていないことに注意したい。
任意の値での剰余を取るには、 ACL の modint
を使うと便利である。
実装例
#include <bits/stdc++.h> using namespace std; #if __has_include(<atcoder/all>) #include <atcoder/all> using namespace atcoder; #endif #define rep(i, start, end) for (auto i = (start); (i) < (end); (i)++) // ======================================== // using mint = static_modint<1000000000>; int main() { int N, K; cin >> N >> K; vector<mint> A(N + 1), S(N + 1); rep(i, 0, min(K, N + 1)) { A[i] = 1; S[i] = A[i]; if (i >= 1) { S[i] += S[i - 1]; } } rep(i, K, N + 1) { A[i] = S[i - 1]; if (i - K >= 1) { A[i] -= S[i - K - 1]; } S[i] = S[i - 1] + A[i]; } cout << A[N].val() << endl; return 0; }
実装時間: 10分
コメント
累積和を前計算しないタイプのやつは久々かも。