Processing math: 24%

freee Programming Contest 2023(AtCoder Beginner Contest 310)G問題メモ

freee Programming Contest 2023(AtCoder Beginner Contest 310)

男子達が水泳をやる会社ではなく、会計管理サービスを中心に提供する会社。

G - Takahashi And Pass-The-Ball Game

問題

  • N 人の人がいて、はじめ、それぞれ B1,...,BN 個のボールを持っている
  • 数列 A=(A1,...,AN) に従って、「人 iAi に自分が持っている全てのボールを渡す」という操作を1回とする
    • ボールは全ての人が同時に渡す
  • この操作を繰り返す回数を 1K から一様ランダムに決める
  • 全ての操作後、各人が持っているボールの個数の期待値を \mod{998244353} で求めよ
  • 1 \le N \le 2 \times 10^5
  • 1 \le K \le 10^{18}

解法

求めるのは期待値だが、K で割る前の値である「1,2,...,K 回操作後に渡されるボールの個数の合計」が各人についてわかればよい。

つまり、各頂点 i から 1,...,K 回後に訪れる頂点のそれぞれに B_i を加算したい。
もちろんこれを愚直に行うことは時間制約上できない。

i→A_i に辺を張ったグラフはFunctional Graphなので、各連結成分はループが1つとそこに流入する木からなることを利用する。

「ループ上」「木の根に向かうパス上」それぞれにおける区間加算は、累積和を用いて高速化できる。

加算したい頂点がループ上か木上かを区別して、別々に扱うことで実現できる。

ループ上の累積和

ループ上の累積和は、適当な点で切り開いて、「どこから累積和を始めるか」を固定することが重要となる。

その上で、「①最初の周回の末尾まで」「②周回分」「③残り」の3つに分けて加算するとやりやすい。

○→○→●→○→○
        Bi
            + ---- -           ①
+ ---------------- -  x周回分  ②
+ ---- -                       ③

木上の累積和

ループ上の各頂点を根とした木をDFSで辿る。

ループ     r
→○→○→◎→○→○→
          ↑
          ◎
         ↗↖        i
        ○  ◎←◎←●

r までのパスを持ちながらDFSする。木上の累積和で加算するのは

  • i のすぐ次の頂点 A_iAns[A_i]+=B_i
  • K 回目の操作で渡す対象が、まだ根を除く木上かどうかで変化(パスの長さで判断できる)
    • 木上なら、その親頂点を p とし、Ans[p]-=B_i
    • ループに入るなら、残り回数(K- 根までの距離)だけ、r を始点としてループ上の累積和に加算

このようにし、葉から根に向かって累積和を取っていく(Ans[A_i]+=Ans[i])と、 パスへの区間加算を表現できる。

Python3

programming_algorithm/contest_history/atcoder/2023/0715_abc310.txt · 最終更新: 2023/07/26 by ikatakos
CC Attribution 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0