Toy と帽子と ADP BE

主にプログラミングに関わる話をゆるくエモくやっていきます

AtCoder diverta 2019 Programming Contest

残念ながらサーバートラブルの影響で今回はUnratedとなったようです。

もしRatedだったら、ABC帯の参加者にとっては、まさかの4完早解き競争になってた!?

各問題

A - Consecutive Integers

入出力例見るまで、問題の意味が頭に入ってきませんでした。酔いの影響か?

例えばN=8 K=3なら

12345678
123
 234
  345
   456
    567
     678

で6通りということですね。

B - RGB Boxes

これも問題の意味がすんなり頭に入ってきませんでした。やっぱり酔いの影響か?

二重ループを回してrとgを決めてから、それに対応するbが存在しうるかどうかを計算して求めれば間に合う典型のやつですね。

C - AB Substrings

  • 各文字列中にある"AB"を数える
  • 先頭の"B"と末尾の"A"を数えて、少ない方の数だけさらに"AB"が組めるので加算する
    • ただし、「"B"ではじまり"A"で終わる」文字列以外に先頭の"B"と末尾の"A"が一つもなかった場合、組める数が一つ減る
      • 循環してしまうので

という感じです。

私は先頭の"B"と末尾の"A"が一つもなかった場合にも、組める数が一つ減るのロジックが働いてしまい、1WAを出してしまいました。 考察はあっているのに実装でミスるとは・・・。on_

D - DivRem Number

ロジック自体は極めて単純で、個人的には1012からいかに枝狩りできるかの問題でした。 なんか数学的にシンプルな解法があるんだろうなぁとは思いつつ。(editorialにはもちろんそのシンプルな解法が書いてありました。)

で、ちょっと考えてわからなかったので、とりあえず結果を全部出力してみます。

// N=1000の場合(抜粋)

125/ 8:0
126/ 7:118
127/ 7:111
128/ 7:104
129/ 7:97
130/ 7:90
131/ 7:83
132/ 7:76
133/ 7:69
134/ 7:62
135/ 7:55
136/ 7:48
137/ 7:41
138/ 7:34
139/ 7:27
140/ 7:20
141/ 7:13
142/ 7:6
143/ 6:142

商が同じになる範囲について、余りは大きい数字から始まり商の数だけ減少していくことがわかります。 なので、1から順に計算して、商が変わったタイミングで余りを商で割ってみて

  • 割り切れた場合
    • お気に入りの数がありかつそれは計算で求まるのでその数字まですっ飛ばすことができる
  • 割り切れなかった場合
    • お気に入りの数はないので、商が変わるところまですっ飛ばすことができる

という方法で、大幅に計算量を削減することができました。

可視化するとこんな感じです。

(前略)
126/ 7:118      // 118 % 7 != 0 なので商=6まで飛ぶ
143/ 6:142      // 142 % 6 != 0 なので商=5まで飛ぶ
167/ 5:165      // 165 % 5 == 0 なので N / x = 5 かつ N % x = 5 となる x まで飛ぶ
199/ 5:5          // x が求められているので、xを答えに加算して商=4になるところまで飛ぶ、でもいいですね
200/ 5:0
201/ 4:196      // 以下同様
249/ 4:4
250/ 4:0
251/ 3:247
334/ 2:332
499/ 2:2
500/ 2:0
501/ 1:499
999/ 1:1
2257

まとめ

考察してわからなかったら実際にやってみるが重要だった回。

Unratedになったのは残念でしたが(個人的にはパフォ自己べを余裕で更新していたっぽいのでなおさら)、まあこんなときもありますよね。