ABC297 F問題 Minimum Bounding Box 2

atcoder.jp

期待値の求め方

マスの数は H \times W個で、ここから K 個 の選び方は、 {}_{H \times W} \mathrm{C}_{K} 通りです。
選んだマスの位置を \left(x_1,y_1\right), \left(x_2,y_2\right), \cdots , \left(x_K,y_K\right) とすると、スコアは \left(\max\left(x_i\right) - \min\left(x_i\right) + 1 \right) \times \left(\max\left(y_i\right) - \min\left(y_i\right) + 1 \right) となります。

スコアが h \times w になる選び方が N_{h,w} 通りあるとすると、スコアの期待値は
 \displaystyle \frac{1}{{}_{H \times W} \mathrm{C}_{K}}\sum_{h=1}^{H} \sum_{w=1}^{W} \left(h \times w \times N_{h,w} \right)
と計算されます。ここから  N_{h,w} を求めることを考えていきます。

場合の数の計算

 h マス、横 wマスの固定範囲内で  K マスの選び方は  {}_{h \times w} \mathrm{C}_{K} 通りですが、これにはスコアが h \times w より小さな選び方も含んでいます。
そこで外側の4辺について、辺上に選んだマスがある場合(〇)とひとつも無い場合(×)で分類します。これによってマスの選び方を 2^4 = 16種類に分類できます。

求めたいのは、①の場合の数です。

選び方全体
 {}_{h \times w} \mathrm{C}_{K} = ①+②+③+④+⑤+⑥+⑦+⑧+⑨+⑩+⑪+⑫+⑬+⑭+⑮+⑯

辺A のマスを選ばない選び方
 {}_{(h-1) \times w} \mathrm{C}_{K} = ⑨+⑩+⑪+⑫+⑬+⑭+⑮+⑯

辺C のマスを選ばない選び方
 {}_{(h-1) \times w} \mathrm{C}_{K} = ③+④+⑦+⑧+⑪+⑫+⑮+⑯

辺B のマスを選ばない選び方
 {}_{h \times (w-1)} \mathrm{C}_{K} = ⑤+⑥+⑦+⑧+⑬+⑭+⑮+⑯

辺D のマスを選ばない選び方
 {}_{h \times (w-1)} \mathrm{C}_{K} = ②+④+⑥+⑧+⑩+⑫+⑭+⑯

辺A,B のマスを選ばない選び方
 {}_{(h-1) \times (w-1)} \mathrm{C}_{K} = ⑬+⑭+⑮+⑯

辺B,C のマスを選ばない選び方
 {}_{(h-1) \times (w-1)} \mathrm{C}_{K} = ⑦+⑧+⑮+⑯

辺C,D のマスを選ばない選び方
 {}_{(h-1) \times (w-1)} \mathrm{C}_{K} = ④+⑧+⑫+⑯

辺D,A のマスを選ばない選び方
 {}_{(h-1) \times (w-1)} \mathrm{C}_{K} = ⑩+⑫+⑭+⑯

辺A,C のマスを選ばない選び方
 {}_{(h-2) \times w} \mathrm{C}_{K} = ⑪+⑫+⑮+⑯

辺B,D のマスを選ばない選び方
 {}_{h \times (w-2)} \mathrm{C}_{K} = ⑥+⑧+⑭+⑯

辺A,B,C のマスを選ばない選び方
 {}_{(h-2) \times (w-1)} \mathrm{C}_{K} = ⑮+⑯

辺A,D,C のマスを選ばない選び方
 {}_{(h-2) \times (w-1)} \mathrm{C}_{K} = ⑫+⑯

辺A,B,D のマスを選ばない選び方
 {}_{(h-1) \times (w-2)} \mathrm{C}_{K} = ⑭+⑯

辺C,B,D のマスを選ばない選び方
 {}_{(h-1) \times (w-2)} \mathrm{C}_{K} = ⑧+⑯

4辺すべてのマスを選ばない選び方
 {}_{(h-2) \times (w-2)} \mathrm{C}_{K} = ⑯


以上の16式から16個の変数を求めると、 {}_{p \times q} \mathrm{C}_{K} = F(p,q) と表示することにして
 ⑯ = F(h-2,w-2)
 ⑧=⑭=F(h-1,w-2)-F(h-2,w-2)
 ⑫=⑮=F(h-2,w-1)-F(h-2,w-2)
 ④=⑦=⑩=⑬= F(h-1,w-1)-F(h-1,w-2)-F(h-2,w-1)+F(h-2,w-2)
 ⑥= F(h,w-2)-2F(h-1,w-2)+F(h-2,w-2)
 ⑪= F(h-2,w)-2F(h-2,w-1)+F(h-2,w-2)
 ②=⑤=F(h,w-1)-2F(h-1,w-1)-F(h,w-2)+2F(h-1,w-2)+F(h-2,w-1)-F(h-2,w-2)
 ③=⑨=F(h-1,w)-2F(h-1,w-1)-F(h-2,w)+2F(h-2,w-1)+F(h-1,w-2)-F(h-2,w-2)
 ①= F(h,w)-2F(h-1,w)-2F(h,w-1)+4F(h-1,w-1)+F(h,w-2)+F(h-2,w)-2F(h-1,w-2)-2F(h-2,w-1)+F(h-2,w-2)

 h マス、横 wマスの範囲の選び方は  \left(H-h+1\right) \times \left(W-w+1\right) 通りあるため、結局、
 N_{h,w}=\left(H-h+1\right) \times \left(W-w+1\right) \times ①
となります。

コード例 (Julia)

const MOD_ = 998244353

const NMAX = 1_000_000

fact    = Vector{Int}(undef, NMAX)
invfact = Vector{Int}(undef, NMAX)

function setup_fact( )
  fact[1] = 1
  invfact[1] = 1
  for i = 2:NMAX
    fact[i] = (i * fact[i-1]) % MOD_    # N!
    invfact[i] = invmod(fact[i],MOD_)   # 1/N!
  end
end

function Comb( N, M )
  if N < 0 || M < 0 || N - M < 0
    return 0
  end
  if M == 0 || N - M == 0
    return 1
  end

  ret = (invfact[M] * invfact[N-M])%MOD_
  ret *= fact[N]
  return ret % MOD_
end

function solve()


  # あらかじめ n!, 1/n! を計算
  setup_fact()

  # 入力
  readInts() =  parse.(Int,split(readline()))
  readInt()  =  parse(Int,readline())

  H,W,K = readInts()

  F = zeros(Int, H, W)

  for h=1:H, w=1:W
    F[h,w] = Comb( h*w, K )
  end

  ans = 0

  for h=1:H, w=1:W
    maru1 = F[h,w]
    maru1 += (h>1) ? -2*F[h-1,w] : 0
    maru1 += (w>1) ? -2*F[h,w-1] : 0
    maru1 += (h>1&&w>1) ? 4*F[h-1,w-1] : 0
    maru1 += (w>2) ?   +F[h,w-2] : 0
    maru1 += (h>2) ?   +F[h-2,w] : 0
    maru1 += (h>1&&w>2) ? -2*F[h-1,w-2] : 0
    maru1 += (h>2&&w>1) ? -2*F[h-2,w-1] : 0
    maru1 += (h>2&&w>2) ?   +F[h-2,w-2] : 0
    maru1 %= MOD_
    if maru1 < 0
      maru1 += MOD_
    end
    coef = h * w * (H-h+1) * (W-w+1)
    coef %= MOD_
    ans += coef * maru1
    ans %= MOD_
    if ans < 0
      ans += MOD_
    end
  end

  ans *= invmod(F[H,W], MOD_)
  ans %= MOD_

  println(ans)

end  # function solve

# main
solve()