競技プログラミング日記

主に AtCoder の記事です

AtCoder Beginner Contest 241E

ABC241E

ダブリングで求める.
問題文通りに実装を考えてみる. 皿に乗っている個数を \(x \in \mathbb{N}\) 個としたとき, 次に乗っている個数を \(f(x) \in \mathbb{N}\) 個とする. \(x_{0} \in \mathbb{N}\) を指定したときの \(f^{K}(x_{0})\) を求めれば良い. これは,理屈ではダブリングで求まるが,現実には不可能. \(f\) の定義域,値域として考えうる値が大きくなるため.

対策: 愚直に \(f\) を求めるのではなく,差分を求める. 皿に \(x\) 個乗っているときに,追加する個数を \(g(x)\) 個とする. これは,追加する個数のルールから, \(x \in N\) に対してだけ \(g(x)\) を求めれば良い.
そのため,\(f\) のときと違って,\(g\) は定義域と値域が \(\mathbb{Z}/ N\mathbb{Z}\) に絞れた.

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

int main() {
  ll n, k;
  cin >> n >> k;
  vll a(n); rep(i,n) { cin >> a[i]; }

  vvll dp(62, vll(n));
  rep(x,n) dp[0][x] = a[x];
  rep(k,61) rep(x, n){
    dp[k+1][x] = dp[k][x] + dp[k][(x + dp[k][x])%n];
  }
  ll ans = 0;
  ll e = 0;
  while(k){
    if(k&1){
      ans += dp[e][ans%n];
    }
    k >>= 1;
    e++;
  }
  cout << ans << endl;

  return 0;
}