Loading [MathJax]/extensions/TeX/mathchoice.js

AtCoder Regular Contest 200 (Div. 2) A,B,C,D,E問題メモ

A - Dot Product

問題文

  • 長さ N の正整数列 A=(A1,A2,,AN),B=(B1,B2,,BN) が与えられます。
  • 以下の条件を全て満たす整数列 X=(X1,X2,,XN) が存在するか判定し、存在するなら一つ求めてください。
    • 108Xi108 (1iN)
    • Ni=1AiXi>0
    • Ni=1BiXi<0
  • T 個のテストケースが与えられるので、それぞれについて答えを求めてください。

制約

  • 1T2×105
  • 1N2×105
  • 1Ai,Bi105
  • 全てのテストケースにおける N の総和は 2×105 以下
  • 入力される値は全て整数

解法

C=Ni=1AiXi,  D=Ni=1BiXi とする。

N=1 のとき

Ai,Bi は正より、C,D も両方正か両方負にしかできないので不可能。

N=2 のとき

(Ai,Bi)gcd(Ai,Bi) で割って、互いに素にしたものを (Ai,Bi) とする。

(A1,B1)=(A2,B2) の時は不可能である。
(C,D) が取り得る領域は y=B1A1x 上の直線上にしか存在せず、この直線は第1と第3象限しか通らない。

それ以外の時、以下のようにできる。

A    20   25
B    31   41

まず、Aを揃える。

 X   25   20
AX  500  500
BX  775  840

この例では BX1 < BX2 なので、X=(25,-20) とすれば、C=0, D<0 にできる。

また、Bを揃える。

 X   41   31
AX  840  775
BX 1271 1271

この例では AX1 > AX2 なので、X=(41,-31) とすれば、C>0, D=0 にできる。

そしてこれは線形的に合成できるので、
X=(25+41, -20-31) とすれば、C>0,D<0 にできる。

 X   66   -51
AX 1320 -1275  →  C =  45 > 0
BX 2046 -2091  →  D = -45 < 0

大小関係が逆の場合は符号が逆になる。

2×105(Amax+Bmax)Xi(Amax+Bmax)2×105 より、値の範囲も大丈夫。

N3 のとき

全ての (Ai,Bi) が一致していたら不可能。

それ以外の場合、(Ai,Bi) が異なる2つを持ってきて、N=2 の時に帰着し、他は 0 にすればよい。

Python3

B - LCM

問題文

  • 正整数 A1,A2,A3 が与えられます。
  • 以下の条件を全て満たす正整数の組 (X1,X2) が存在するか判定し、存在する場合は一組求めてください。
    • X1 は十進法で A1 桁の整数である。
    • X2 は十進法で A2 桁の整数である。
    • X1X2 の最小公倍数は十進法で A3 桁の整数である。
  • T 個のテストケースが与えられるので、それぞれについて答えを求めてください。

制約

  • 1T173
  • 1A1,A2,A317
  • 入力される値は全て整数

解法

互いに素な X1,X2 なら、最小公倍数は X1×X2 になるので桁数がわかりやすい。
そういう方向に持ってけないか考える。

a 桁× b 桁は、a+b1 または a+b 桁となる。

a=4, b=5
最小: 1000 * 10000 =  10000000  →8桁
最大: 9999 * 99999 = 999890001  →9桁

最小公倍数は2数の積より大きくはならないので、A1+A2<A3 なら不可能。
また、最小公倍数は元の数より小さくならないので、A1>A3A2>A3 の場合も不可能。

それ以外の場合、互いに素であることが保証される素数を使って、構築できる。
直接的に A1+A2=A3 または A1+A2=A31 という関係性に無い場合は、末尾に0を追加して調整する。

xはa桁、yはb桁、x,yは互いに素、z=xy

LCM( x0000 , y0000 ) = z0000
     ~~~~~   ~~~~~     ~~~~~
     a+4桁   b+4桁     a+b+4 または (a+b-1)+4 桁

A1+A21A3A1+A2 になるまで、A1,A2,A3 から1ずつ引いていく。
この時引いた回数を d、引いた結果を A1,A2,A3 として、X1,X2 は以下のように作れる。

  • A3=A1+A21 の時
    • X1=A1 桁の最小の素数
    • X2=A2 桁の2番目に小さい素数
  • A3=A1+A2 の時
    • X1=A1 桁の最大の素数
    • X2=A2 桁の2番目に大きい素数
  • X1=X1 の末尾に0を d 個追加したもの
  • X2=X2 の末尾に0を d 個追加したもの

この方法で X1×X2A3 桁となり、X1×X2A3 桁となる。
素数はわりと密に存在するので、各桁の最小や最大(10009999 など)から多少ずれたとしても、積の桁数が変わるほどずれることはない。

k 桁の最小・最大の素数」を得るには、Pythonなら sympy.nextprime, prevprime が使える。

Python3

C - Movie Theater

問題文

  • 正整数 N と長さ N の正整数列 L=(L1,L2,,LN),R=(R1,R2,,RN) が与えられます。
    • ここで、 L1,L2,,LN,R1,R2,,RN は全て互いに異なることが保証されます。
  • ある映画館には N 個の席が左右一列に並んでいます。左から i 番目の席を席 i と呼びます。
  • この映画館に人 1 から人 N までの N 人の人が訪れます。あなたは各人に席を 1 つずつ割り当てます。
  • i に割り当てた席を Pi とすると、人 i は時刻 Li に席 1,2,,Pi1 を横切って席 Pi に座り、時刻 Ri に席 1,2,,Pi1 を横切って席から離れます。
  • i の 不満度 を時刻 Li から時刻 Ri までの間(ちょうど Li,Ri は含まない)に他の人に席 Pi を横切られた回数とします。
  • 1 から人 N までの N 人の不満度の総和が最小となる (1,2,,N) の順列 P のうち辞書順最小のものを求めてください。
  • T 個のテストケースが与えられるので、それぞれについて答えを求めてください。

制約

  • 1T500
  • 1N500
  • 1Li<Ri2×N
  • L1,L2,,LN,R1,R2,,RN は全て互いに異なる
  • 全てのテストケースにおける N の総和は 500 以下
  • 入力される値は全て整数

解法

答えが逆(シート i に誰を座らせるか)という問題だったらトポロジカルソートで簡単に求まるのに、、、
「人 i をどのシートに座らせるか」を辞書順最小にするのに意外と手こずった。

[Li,Ri] を数直線にプロットし、その関係性を3種類に場合分けする。

■交わらない

  |----1----|     |---2---|

この場合、お互いに不満度を与えることはない。
座らせるシートの左右位置関係はどちらでも良い。

■交差する
  |----1----|
     |----2----|

人1を左に座らせると、人2の入館時に1が不満を1覚える。
人2を左に座らせると、人1の退館時に2が不満を1覚える。
どちらにしろ不満が1増えるのは変わらないので、座らせる位置関係はどちらでもよい。

■包含する
  |-------1-------|
     |----2---|

人1を左に座らせると、人2の入館時と退館時に不満を2覚える。
人2を左に座らせると、不満は増えない。
よってこの場合は、人2を左に座らせないといけない。P2 < P1 となる。

一部の P の値に大小関係の制約ができたが、包含関係のみに由来するのでこの制約は推移的である。
つまり、Pi<Pj かつ Pj<Pk となる (i,j,k) に対し、Pi<Pk が必ず成り立ち、矛盾することはない。

この制約、つまり「入退館時刻が包含関係にある2人は、短い方を左のシートに座らせる」というルールさえ守っていれば、不満度最小は達成できる。

i=1 から、「シートの範囲と、この範囲のシートに座らせる人の集合」を分割していくように貪欲に求めていける。

例えば N=8 で、

  • P1>Pi となるような i : {3,5,8}
  • P1<Pi、または 1 との制約がない i : {2,4,6,7}

に分けられる場合、人 1 はなるべく左に座らせたい(P1 を小さくしたい)ので、 3,5,8 のみ左に座らせ、人 1 は4番目のシートに座ることになる。P1=4 と決まる。

シートに誰を座らせるか(P の逆順列)の順列を Q とすると、このように部分的に決まる。

i   1 2 3   4   5 6 7 8
Q  {3,5,8}  1  {2,4,6,7}

iQ(ひいては Pii)の対応が分割され、左と右で再帰的に同じような問題と見なせる。

たとえば左では、{3,5,8} のうち最小の番号の人が 3 なので、P3 の値を最小にすることを考える。

  • {5,8} のうち、P3>Pi となるような i : {8}
  • {5,8} のうち、P3<Pi または制約がない i : {5}

だったとすると、以下のように決まる。

i   1   2   3   4   5 6 7 8
Q  {8}  3  {5}  1  {2,4,6,7}

このように、グループのうち番号が最小の人の座るシートを決めていくと、O(N2) で解ける。

Python3

D - |A + A|

問題文

  • 正整数 M,K が与えられます。
  • 以下の条件を全て満たす正整数 N と整数列 A=(A1,A2,,AN) が存在するか判定し、存在するなら一つ求めてください。
    • 1NM
    • 0Ai<M (1iN)
    • k\equiv A_i+A_j \pmod M を満たす添字の組 (i,j) が存在するような整数 0\le k \lt M がちょうど K 個存在する。
  • T 個のテストケースが与えられるので、それぞれについて答えを求めてください。

制約

  • 1\le T\le 2\times 10^5
  • 1\le K\le M\le 2\times 10^5
  • 全てのテストケースにおける M の総和は 2\times 10^5 以下
  • 入力される値は全て整数

解法

3つめの条件がちょっと分かりづらいが、要は100ますけいさんのように数列 A を縦と横に書いて足し算(mod)して、 その表に表れる数字の種類数が K 個になるように A を決めよ、と言っている。

  | 3  1  4
--+---------
3 | 6  4  7     2,4,5,6,7,8 の6種類
1 | 4  2  5
4 | 7  5  8

言わずもがな表の値は対角線を挟んで対称なので、右上の部分のみ考える。

いろいろ実験してみる。シンプルに、A=(0,1,2,...) としてみると、

  | 0  1  2  3     A=(0,1,...,x) とすると、
--+------------    0~2x の 2x+1 個の値が現れる。
0 | 0  1  2  3
1 |    2  3  4
2 |       4  5
3 |          6

A=(0,1,2,...,\frac{K-1}{2}) とすることで、K が奇数の場合は必ず構築できるとわかる。

では、K が偶数の場合は?

何となく、\mod{M} を利用することを考えると訳わかんなくなりそうなので、まずはなるべく和が M 未満に収まるようなものを考えたい。
上記の場合は 0~2x の値が使われたが、では、A=(0,2,3,...,x) とすると 1 だけを使わないようにできるのでは?

     | 0  2  3  4  5
   --+---------------
   0 | 0  2  3  4  5
   2 |    4  5  6  7
   3 |       6  7  8
   4 |          8  9
   5 |            10
        ┘ ┘ ┘ ┘ ┘
種類数  1  3  6  8  10

K \ge 6 の偶数なら狙い通りとなり、A=(0,2,3,...,\frac{K}{2}) でできそう。
ただし、K=M の時、たとえば K=M=8 の時、 A=(0,2,3,4) とすると 4+4=8 がmodで 0 になってしまい、7 種類になってしまう。

しかしこの場合は、そもそも 0~M-1 を全て出現させれば良いので、適当に密に作ればよい。
A=(0,1,...,M-1) などがあてはまる。

これを最初に判定して除けば、K \ge 6 の偶数ならできることが分かった。

残るは K=2,4 の時のみ。
愚直ケースを書いて調べると、MK の倍数の時は、 (0,\frac{M}{K},2\frac{M}{K},...,(K-1)\frac{M}{K}) を和に全て出現させることで達成できることがわかる。

M=12  K=4

  | 0  3  6  9     K=M の場合の応用バージョン
--+------------
0 | 0  3  6  9
3 |    6  9  0
6 |       0  3
9 |          6

K=2,4MK の倍数でない時にできない証明がなかなか難しいが、まぁ、愚直でここまで綺麗な法則が現れたら大丈夫やろと信じれば通る。

証明は公式Editorial参照。

まとめると、(上から順に判定して当てはまれば終了)

  • MK の倍数なら、A=(0,\frac{M}{K},2\frac{M}{K},...,(K-1)\frac{M}{K})
  • K が奇数なら、A=(0,1,2,...,\frac{K-1}{2})
  • K が6以上の偶数なら、A=(0,2,3,...,\frac{K}{2})
  • それ以外は不可能

Python3

E - popcount <= 2

問題文

  • 正整数 N,M が与えられます。
  • 長さ N の非負整数列 A=(A_1,A_2,\ldots,A_N) であって、以下の条件を全て満たすものの個数を 998244353 で割ったあまりを求めてください。
    • 0\le A_i \lt 2^M (1\le i\le N)
    • \operatorname{popcount}(A_i\oplus A_j) \le 2 (1\le i \lt j\le N)
  • T 個のテストケースが与えられるので、それぞれについて答えを求めてください。

制約

  • 1\le T\le 2\times 10^5
  • 2\le N,M \lt 998244353
  • 入力される値は全て整数

解法

丁寧な場合分け。

まず、条件を満たす数列 A の各要素に対し 1 以上 2^M 未満の同じ値をXORしたものも、 また別の条件を満たす数列となる。
よって A_1=0 の場合を考えることとし、最終的な答えはそれを 2^M 倍すればよい。

A_1=0 の時、当然、他の全ての要素のpopcountは 2 以下でなければならない。

\max(\operatorname{popcount}(A_i)) \le 1

全ての A_i が、0 または1つだけbitが立っている数列は条件を満たす。

i=2~N につき、A_i の選択肢が M+1 通り、独立にあるので、(M+1)^{N-1} 通り。

\max(\operatorname{popcount}(A_i)) = 2

愚直を書いて観察すると、3パターンに分かれて考えられそう。

  • ①ある共通のbit1つと、他に高々1つのbitが立っている場合
  • \{00,01,10,11\} の4つからなる場合
  • \{000,011,101,110\} の4つからなる場合

こんなやつ

00000000
00001010
00101000
10001000
00001000
00011000
    ^ 共通のbit

共通のbit位置が M 通りある。それを固定したとき、A_2~A_{N} に置く数は以下の M+1 通りが選択肢としてあり得る。

  • a) 他にどこか立っている M-1 通り
  • b) 共通のbitのみが立っている
  • c) 0

このうち、「b) または c) のみからなる」ものは、\max(\operatorname{popcount}(A_i)) \le 1 で既に数えられている。

また、「a) または c) のみからなり、a) で共通のbitの他に立てたbitが全てで一致」するものは、 ①の過程で2回ずつ重複して数えられる。

よって、共通bitを固定すると (M+1)^{N-1}-2^{N-1}-\frac{(2^{N-1}-1)(M-1)}{2} の組合せがある。
この M 倍が①の場合の答えとなる。

②,③

補足すると、「\{00,01,10,11\} の4つからなる」とは、M 個中どこか2箇所のbitを選んで、 それが (0,0),(0,1),(1,0),(1,1) のどれか、他は 0 である状態を示す。

どのbitを選ぶかは、②は {}_M C_2 通り、③は {}_M C_3 通りある。
これを固定した場合を考えて、あとで倍加する。

いずれも、4つ全てが出現する場合以外は既に数えられている。

0A_1 で必ず出現することに注意して包除原理を適用すると、 A_2 以降の決め方は 4^{N-1} - 3 \times 3^{N-1} + 3 \times 2^{N-1} - 1 通りずつある。

この ({}_M C_2 + {}_M C_3) 倍が、②③の場合の答えとなる。

Python3

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