Processing math: 100%

AtCoder Beginner Contest 276 F,G 問題メモ

F - Double Chance

問題

  • N 枚のカードがあり、カード i には整数 Ai が書かれている
  • K=1,2,...,N について、次の問題を解く
  • 問題
    • カード 1K の中から、等確率でカードを1枚引き、戻すことを2回繰り返す
    • 1回目と2回目に引いた数をそれぞれ x,y とすると、max(x,y) をその試行の得点とする
    • 得点の期待値を mod998244353 で求めよ
  • 1N2×105
  • 1Ai2×105

解法

たとえば K=41,4,7,10 が書かれたカードから引く場合を考えると、 全試行パターンは1回目と2回目で4通りずつなので、K2=16 通り。

期待値は、全ての場合の得点を合計してこの K2 で割ればよいので、合計の方を求められればよい。

得点ごとに、そのパターン数を考えると

得点が1になる場合:  1を2回連続で引く              1x1       = 1 通り
得点が4になる場合:  1,4から2回連続で引く場合から
                    得点が1になる場合を除く       2x2 - 1x1 = 3 通り
得点が7になる場合:  3枚から2回連続で引く場合から
                    得点が1,4になる場合を除く     3x3 - 2x2 = 5 通り
得点が10になる場合: 4枚から2回連続で引く場合から
                    得点が1,4,7になる場合を除く   4x4 - 3x3 = 7 通り

1x1 + 4x3 + 7x5 + 10x7 = 118

小さい順に 1,3,5,...(奇数)通りずつパターン数が増えていく。得点とパターン数を掛け合わせればよい。
(同じ数字があった場合も、適当に順番を決めて扱えばよい)

で、この K=4 の値から K=5 の値を求められる。

A5=6 を追加した場合、

  得点 パターン数
     1      1
     4      3
New! 6      5
     7   5→7
    10   7→9

3番目に追加されるのでパターン数は5となり、6×5 が新たに増える。
また、それより大きい値の 7,10 は、1つにつき 2 ずつパターン数が増える。

なので、

  • 追加する Ai より小さい値が何個あるか p
  • 追加する Ai 以上となる値の合計はいくらか q

が、逐次求められればよいことになる。(Ai×(2p+1)+2q だけ増える)

これは、Ai をindexとして個数を管理するFenwick Treeと、合計を管理するFenwick Treeの2本を使って 1回あたり logAmax で求められる。

Python3

G - Count Sequences

問題

  • 以下の条件を満たす項数 N の整数列 A=(a1,a2,...,aN) の個数を mod998244353 で求めよ
  • 条件
    • 要素は 0 以上 M 以下で広義単調増加 0a1a2...aNM
    • 隣り合う項(i=1N1 に対し、aiai+1)は、3で割ったあまりが異なる
  • 2N107
  • 1M107

解法

単調増加列の問題は、差分に着目すると上手くいくことがよくある。
末尾と M との差分(下図 b5)まで含めて考えると、差分の総和が上限値 M となる。

A        0   a1   a2   a3   a4   M
Aの差分   b1 + b2 + b3 + b4 + b5    = M

隣り合う項の3で割ったあまりが異なるので、両端を除く b2b4 は、3の倍数であってはいけないということになる。

逆にこれさえ満たせば条件を満たす数列となるため、そのような非負整数列 B=(b1,...,bN+1) の個数を数えればよい。

ここで、B を3で割った商 X=(x1,...,xN+1) とあまり Y=(y1,...,yN+1) に分けて考える。

条件は「y2yN0 禁止(1,2 のいずれか)」「3xi+yi の総和が M」となる。

条件を満たす X,Y は、例えば以下のようにして構築できる。

  • y10,1,2 の中から決める
  • y2yN は最低でも1なのであらかじめ1を敷いておき、「2になる要素がどれか」を決める
  • ここまでに決めた数によって、M の残りから、X の総和と yN+1 は自動的に決まる
  • X の総和の x1,...,xN+1 への割り振り方を決める

以下の2つを固定すると、

  • s: y1 の値(0/1/2 の3通り)
  • k: y2yN のうち、2 になる要素の個数(0N1N 通り)

そのパターン数が O(1) で求められる。

  • y2yN のうちの 2 の配置の決め方は N1Ck
  • X の総和は M(N1)sk3(切り捨て)に決まる。これを t とする
    • x1,...,xN+1 への割り振り方は N+1Ht

この2つを掛け合わせたものが、s,k を固定した時のパターン数となる。全探索して合計すれば答え。

本番では3で割った商とあまりに分割するところまでは思いついたが、b1 を特別視しすぎて b2bN だけで X,Y を考え、b1 は別で計算してしまったため、考慮すべきパターン数が増え、計算量が NM から減らせなかった。

Python3

programming_algorithm/contest_history/atcoder/2022/1105_abc276.txt · 最終更新: 2022/11/07 by ikatakos
CC Attribution 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0