−目次
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) に従って、「人 i は Ai に自分が持っている全てのボールを渡す」という操作を1回とする
- ボールは全ての人が同時に渡す
- この操作を繰り返す回数を 1~K から一様ランダムに決める
- 全ての操作後、各人が持っているボールの個数の期待値を \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_i に Ans[A_i]+=B_i
- K 回目の操作で渡す対象が、まだ根を除く木上かどうかで変化(パスの長さで判断できる)
- 木上なら、その親頂点を p とし、Ans[p]-=B_i
- ループに入るなら、残り回数(K- 根までの距離)だけ、r を始点としてループ上の累積和に加算
このようにし、葉から根に向かって累積和を取っていく(Ans[A_i]+=Ans[i])と、 パスへの区間加算を表現できる。