JIJプログラミングコンテスト 2026(AtCoder Beginner Contest 476)F,G問題メモ

F - Chebyshev Cafe

問題文

  • $N$ 行 $N$ 列のグリッドで表される市街地があります。上から $i$ 行目・左から $j$ 列目のマスをマス $(i,j)$ と表します。
  • マス $(i, j)$ に住む人の人数は $(A_i \times B_j) \bmod M$ です。
  • マス $(s_r,\ s_c)$ に住む人がマス $(t_r,\ t_c)$ に行くときにかかる交通費は1人当たり $\max(|s_r - t_r|,\ |s_c - t_c|)$ です。
  • $f(i,j)$ を以下で定義します。
    • グリッド上の全員をマス $(i, j)$ に集めるときにかかる交通費の合計
  • 各マス $(i,j)$ に対する以下の値をすべてのマスについて求めたときの、それらの bitwise XOR として得られる値を出力してください。
    • $f(i,j) + (i-1)N + (j-1)$

制約

  • $1 \leq N \leq 1500$
  • $2 \leq M \leq 2 \times 10^6$
  • $1 \leq A_i \leq M-1$ ($1 \leq i \leq N$)
  • $1 \leq B_j \leq M-1$ ($1 \leq j \leq N$)
  • 入力される値はすべて整数

解法

$(A_i \times B_j) \bmod M$ という人数の算出方法、および最後のXORは、入力・出力サイズを小さくするためであって、 「この計算方法だからこそ上手く計算できる方法がある」訳ではないと考えた方がよさそう。

つまり、1マスずつ $f(i,j)$ を求めることを考える。

チェビシェフ距離とは、正方形状に広がっていく距離。

3 3 3 3 3 3 3
3 2 2 2 2 2 3
3 2 1 1 1 2 3
3 2 1 0 1 2 3
3 2 1 1 1 2 3
3 2 2 2 2 2 3
3 3 3 3 3 3 3

これを、こう分解すれば、

3 3 3 3 3 3 3     0 0 0 0 0 0 0     0 0 0 0 0 0 0
2 2 2 2 2 2 2     1 0 0 0 0 0 1     0 0 0 0 0 0 0
1 1 1 1 1 1 1     2 1 0 0 0 1 2     0 0 0 0 0 0 0
0 0 0 0 0 0 0  +  3 2 1 0 1 2 3  +  0 0 0 0 0 0 0
1 1 1 1 1 1 1     0 0 0 0 0 0 0     2 1 0 0 0 1 2
2 2 2 2 2 2 2     0 0 0 0 0 0 0     1 0 0 0 0 0 1
3 3 3 3 3 3 3     0 0 0 0 0 0 0     0 0 0 0 0 0 0

左端は行ごとに共有できるので全体で $O(N^2)$ で求められる。

右側の2つだが、これも四隅からDPすれば、$O(N^2)$ 4回で求められる。

Python3

G - Increasing Popcount

問題文

  • $L\le R$ を満たす正整数 $L,R$ が与えられます。
  • 以下の条件を満たす長さ $R-L+1$ の正整数列 $A=(A_L,A_{L+1},\ldots,A_R)$ を良い整数列と呼びます:
    • $L\le i \lt j\le R$ を満たすすべての整数の組 $(i,j)$ に対し、$A_i = A_j$ ならば $\operatorname{popcount}(i)\lt\operatorname{popcount}(j)$ が成り立つ。
  • 良い整数列 $A=(A_L,A_{L+1},\ldots,A_R)$ 全てに対する $\max(A_L,A_{L+1},\ldots,A_R)$ の最小値を求めてください。
  • $T$ 個のテストケースが与えられるので、それぞれについて答えを求めてください。

制約

  • $1\le T\le 10^4$
  • $1\le L \le R\le 10^{18}$
  • 入力される値は全て整数

解法

問題文の理解が少し難しいが、要は

  • $L$ から $R$ までの整数の popcount を並べた数列を $C=(C_L,...,C_R)$ とします。
  • $C$ の各要素を何色かで塗り分けます。この時、同じ色で塗られた要素は左から狭義単調増加でなければいけません。
  • 最低何色要りますか。

という問題だとわかる。 このように数列全体を「狭義単調増加部分列」に分ける最小数は、 Dilworthの定理などと関連し、数列の「最長広義減少部分列」の長さに等しくなる。

よって、「$C$ の最長広義減少部分列の長さ」が答えとなる。 とはいえ、制約の大きさからそのまま求めるわけにはいかない。

ここで、$C$ の持つ性質を観察すると、

iの範囲   C(popcount)                      個数 1 2 3 4 5
 1         1                                      1
 2-3       1 2                                    1 1
 4-7       1 2 2 3                                1 2 1
 8-15      1 2 2 3 2 3 3 4                        1 3 3 1
16-31      1 2 2 3 2 3 3 4 2 3 3 4 3 4 4 5        1 4 6 4 1
  :

例えば $[16,31]$ の列は、「$[8-15]$ の列」と「その各要素に $1$ を足した列」を結合したものとなり、フラクタル構造を持つ。 また、各ブロックに出現するpopcountの個数をカウントすると、二項係数が現れる。 (ブロック毎に一定数のbitから何bit立てるか、という話なので当然ではある)

なので、$[L,R)$(便宜的に半開区間に改める)の範囲を、このような $2^k$ で表せる長さのブロックに分割してみたくなる。

[6, 29)                                               個数
↓       値                        popcount           1 2 3 4
[6,8)    6  7                      2 3                  1 1
[8,16)   8  9 10 11 12 13 14 15    1 2 2 3 2 3 3 4    1 3 3 1
[16,24) 16 17 18 19 20 21 22 23    1 2 2 3 2 3 3 4    1 3 3 1
[24,28) 24 25 26 27                2 3 3 4              1 2 1
[28,29) 28                         3                      1

ちゃんと定義すると、以下のような区間 $S_{n,k}$ に分割する、ということである。

  • ある正整数 $n$ に対し、$\operatorname{LSB}(n)$ を、$n$ で最も低い位置のbitとする。
    • (例)$n=44=101100_{2}$ の場合、$\operatorname{LSB}(44)=2$
  • $0 \le k \le \operatorname{LSB}(n)$ の範囲から $k$ を選ぶ。
  • $[n,n+2^k)$ の区間を、$S_{n,k}$ の表す範囲とする。

(要は、$n$ の末尾に連続する $k$ 個の“0”に対する、“000..0”~“111..1” の範囲、という意味)

区間 $S_{n,k}$ における、popcount として出現する値の個数(上例では右端の表)にはやはり二項係数が現れる。 これは、$\binom{k}{*}$ を $\operatorname{popcount}(n_i)$ だけ右にずらしたものとなる。

もし、以下のような性質があったら、同じ区間内のpopcountの並びは捨てて、 「個数」の2次元配列で考えてよくなるので嬉しい。

  • 分割した各列に対し、最長減少部分列には、同じ列からは全て同じ値が採用される。
    • 例えば、$[8,16)$ からはpopcount “3” のみが採用される、など

そして、この予想は正しい。証明は難しいが、LYM不等式というものを使うとできる。

略証

まとめると、

  • $[L,R)$ を、区間 $S=(S_{n_1,k_1},S_{n_2,k_2},...,S_{n_m,k_m})$ に分割する。
  • $i=1,...,m$ につき、$k_i$ の二項係数を、$\operatorname{popcount}(n_i)$ だけずらした2次元配列を用意する。
[6, 29)       j→
↓            1 2 3 4
[6,8)    i  1|  1 1
[8,16)   ↓ 2|1 3 3 1
[16,24)     3|1 3 3 1
[24,28)     4|  1 2 1
[28,29)     5|    1
  • 2次元配列上でDPする。
    • 各 $i$ から最大1つずつ取るが、取った $j$ については広義単調減少でなくてはいけない。
    • その中で総和が最大となるものが答え

$O(\log^2{R})$ のDPで求められる。

Python3

programming_algorithm/contest_history/atcoder/2026/0919_abc476.txt · 最終更新: by ikatakos
CC Attribution 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0