ABC138-F:Coincidence
経験不足だった。
問題
解法
考察
をで割った余りがに等しいという条件が謎なので,もうすこしわかりやすい条件に言い換えることを目指そう。まず,がある自然数をで割った余りであるということから,が成り立つ。この不等式が成り立つためには,の2進法表記としての桁数は,のそれ以下で必要がある。さらに,であるから,結局との桁数は等しくなければいけない。で両者の2進法表記で桁数が等しいとき,が言える(倍することは桁を1つ増やすことに相当すると考えると明らか)。つまり,をで割ったときの商として考えられるものはしかない。よって,以下の等式を満たすようなの組を数えればよい。
この条件からの各桁について何が言えるかを考える。の桁目がでの桁目がであるとすると,左辺の足し算において繰り上がりが起き,辻褄が合わなくなる(桁目がどうなるかを確認してみるとよい)。逆にそれ以外のパターンでは各桁が他の桁に影響を与えずに,条件が満たされることがわかる。つまり,との桁数が等しく,の桁目をとしたとき,が満たされているようなものを数えればよいことがわかった。このとき,が自動的に保障されるので,以後との大小は気にしなくてよい。
厄介なのはという条件だろう。ここは慣れていないと難しいと思うが,桁dpの考え方を応用する。つまり
- :桁目まで見たときに,がより小さいことが確定しているかどうか(,がより大きいことが確定しているかどうか,を決めたときの条件を満たすの組の場合の数
としてdpを行う。
dpの詳細と実装
bool値を2つ状態としてもつので遷移がややこしく,あまり雑にやると実装が破滅する。落ちついて,「今の状態を固定したときに,何を決めれば次の状態が決まるか」を表にしてみよう。との各桁の関係は重要だが,の桁目を決めたときにについて次にどのような状態になるかはの情報は関係がない。よって,とについて別々に表が作れる。
今桁目までの答えがわかっていて,桁目の答えを知りたいということにしよう。の桁目はと同じで,桁以下はすべて0である数をとする。このとき,dpテーブルのという添え字は,「今はであるか?」ということを意味している。ここから桁目での状態を決定するには,の桁目が何であるかということと,の桁目を何にするかということを決めればよい。これらの関係を表にすると以下のようになる。
の桁目 | の桁目 | 桁目での状態 | 桁目での状態 |
---|---|---|---|
なし | |||
この表を作ってしまえば,桁目の状態と桁目を何にするかをfor文で回し,表を見ながら次の状態を決めるのことができて,実装が簡潔になると(個人的には)思っている。についても同様の表を示しておく。
の桁目 | の桁目 | 桁目での状態 | 桁目での状態 |
---|---|---|---|
なし |
の桁数が等しいという条件をどう組み込むかについて述べるのを忘れていた。最上位の桁として選ぶことができるのは,Rの最上位の桁からの最上位の桁までである。従って,該当する桁ではに適切にを選んでを足しておけばよい(詳細は実装を参照)。これでdpの遷移が完成した。
実装
Submission #7021885 - AtCoder Beginner Contest 138
次の状態はだいたいは不等号なので,デフォルトで不等号にしておいて,特定の場合だけ変えるという実装がわかりやすいと思う。
ところでmodintは便利ですね。