結果

問題 No.1097 Remainder Operation
ユーザー 草苺奶昔草苺奶昔
提出日時 2023-06-17 01:58:53
言語 TypeScript
(5.4.3)
結果
WA  
実行時間 -
コード長 3,934 bytes
コンパイル時間 10,617 ms
コンパイル使用メモリ 259,608 KB
実行使用メモリ 151,632 KB
最終ジャッジ日時 2023-09-07 01:04:20
合計ジャッジ時間 32,348 ms
ジャッジサーバーID
(参考情報)
judge15 / judge12
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 WA -
testcase_01 WA -
testcase_02 WA -
testcase_03 WA -
testcase_04 WA -
testcase_05 WA -
testcase_06 WA -
testcase_07 WA -
testcase_08 WA -
testcase_09 WA -
testcase_10 WA -
testcase_11 WA -
testcase_12 WA -
testcase_13 WA -
testcase_14 WA -
testcase_15 WA -
testcase_16 WA -
testcase_17 WA -
testcase_18 WA -
testcase_19 WA -
testcase_20 WA -
testcase_21 WA -
testcase_22 WA -
権限があれば一括ダウンロードができます

ソースコード

diff #

import * as fs from 'fs'
import { resolve } from 'path'
/**
 * 倍增维护`n`个状态的转移编号和值.
 * 每个状态对应一个`编号(0-n-1)`和`值(幺半群)`.
 * 从状态`a`转移一次到达状态`b`,状态`b`对应的值与`边权`进行结合运算.
 */
class Doubling<E> {
  private readonly _n: number
  private readonly _log: number
  private readonly _e: () => E
  private readonly _op: (e1: E, e2: E) => E
  private readonly _to: Int32Array
  private readonly _dp: E[]
  private _isPrepared = false

  /**
   * @param n 状态的数量.
   * @param maxStep 最大的转移次数.
   * @param e 转移边权的单位元.
   * @param op 转移边权的结合律运算.
   */
  constructor(n: number, maxStep: number, e: () => E, op: (e1: E, e2: E) => E) {
    this._n = n
    this._log = 1
    while (2 ** this._log <= maxStep) this._log++
    this._e = e
    this._op = op

    const size = n * this._log
    this._to = new Int32Array(size)
    this._dp = Array<E>(size)
    for (let i = 0; i < size; i++) {
      this._to[i] = -1
      this._dp[i] = e()
    }
  }

  /**
   * 初始状态(leaves):从 `from` 状态到 `to` 状态,边权为 `weight`.
   * 0 <= from, to < n.
   */
  add(from: number, to: number, weight: E): void {
    if (this._isPrepared) throw new Error('Doubling is prepared')
    if (to < -1 || to >= this._n) throw new RangeError('to is out of range')
    this._to[from] = to
    this._dp[from] = weight
  }

  build(): void {
    if (this._isPrepared) return
    this._isPrepared = true
    const n = this._n
    for (let k = 0; k < this._log - 1; k++) {
      for (let v = 0; v < n; v++) {
        const w = this._to[k * n + v]
        const next = (k + 1) * n + v
        if (w === -1) {
          this._to[next] = -1
          this._dp[next] = this._dp[k * n + v]
          continue
        }
        this._to[next] = this._to[k * n + w]
        this._dp[next] = this._op(this._dp[k * n + v], this._dp[k * n + w])
      }
    }
  }

  /**
   * 从 `from` 状态开始,执行 `step` 次操作,返回最终状态的编号和值.
   * 0 <= from < n.
   * 如果最终状态不存在,返回 [-1, e()].
   */
  jump(from: number, step: number): [to: number, value: E] {
    if (!this._isPrepared) this.build()
    if (step >= 2 ** this._log) throw new RangeError('step is over max step')
    let value = this._e()
    let to = from
    for (let k = 0; k < this._log; k++) {
      if (to === -1) break
      const div = 2 ** k
      if (step % div) {
        const pos = k * this._n + to
        value = this._op(value, this._dp[pos])
        to = this._to[pos]
      }
    }
    return [to, value]
  }

  /**
   * 求从 `from` 状态开始转移 `step` 次,满足 `check` 为 `true` 的最大的 `step`.
   * 0 <= from < n.
   */
  maxStep(from: number, check: (e: E) => boolean): number {
    if (!this._isPrepared) this.build()
    let res = this._e()
    let step = 0
    for (let k = this._log - 1; ~k; k--) {
      const pos = k * this._n + from
      const to = this._to[pos]
      const next = this._op(res, this._dp[pos])
      if (check(next)) {
        step += 2 ** k
        from = to
        res = next
      }
    }
    return step
  }
}

function useInput(path?: string) {
  let data: string
  if (path) {
    data = fs.readFileSync(resolve(__dirname, path), 'utf8')
  } else {
    data = fs.readFileSync(process.stdin.fd, 'utf8')
  }

  const lines = data.split(/\r\n|\r|\n/)
  let lineId = 0
  const input = (): string => lines[lineId++]

  return {
    input
  }
}

const { input } = useInput()

const n = Number(input())

const D = new Doubling(
  n,
  1e12 + 10,
  () => 0,
  (a, b) => a + b
)

const nums = input().split(' ').map(Number)
for (let i = 0; i < n; i++) {
  D.add(i, (i + nums[i]) % n, nums[i])
}

const q = Number(input())
for (let i = 0; i < q; i++) {
  const step = Number(input())
  const [_, value] = D.jump(0, step)
  console.log(value)
}
0