Grenache's blog

競技プログラミング初心者です。

カテゴリ: yukicoder

AtCoder のAC数と yukicoder のAC数を足し合わせてTop20ランキングを作成しました。ユーザ名はAtCoderのユーザIDになっています。
AtCoderのIDとyukicoderのIDのマッチングで間違いがあったら、ご指摘ください。
AtCoderのAC数はAtCoder Problemsからいただいています。
(Top20に変更。160704)

問題概要

問題文はこちらを参照してください。

コンテスト後の解説放送中に話題に出たDPを使った解法を書きました。数値が$n$以下という制限がないのでいわゆる桁DPというよりは、「AtCoder Typical DP Contest Q 連結」の解説のような1文字ずつ増やしていくDPが近いのかなと思います。また、$n$番目の組み合わせを求めるというのは、「AtCoder Typical DP Contest G 辞書順」の解説に出てくるやり方です。

解法

まずは作問者の方の解説に書いてある条件をもとに、この問題を「"3"と"5"からなる長さ$1~L$の文字列のうち、1桁目が"5"であり、各桁の数字の和が3の倍数であるような文字列の組み合わせの中で、$n$番目の数を求めよ」と読みかえます。

漸化式の定義: $$dp[i+1][l][(k + d[l])\mod 3]+=dp[i][j][k]$$ $$d[l]=\{3, 5\}$$

$dp[i][j][k]$:$i$文字目(1桁目から数える)が$d[j]$という数のときにそれまでの各桁の数字の和を3で割った余りが$k$である文字列の組み合わせの数
$(0\le i \le 25,\ 0\le j,l \le 1,\ 0\le k \le 2)$

初期値:$dp[1][1][2]=1$(1文字目が"5"のとき、つまり3で割った余りが2のときのみ存在する)

求める解:$dp[i][j][0]$。$i$文字目が$d[j]$のときに各桁の数字の和を3で割った余りが0である組合せの数となる。

このように$i$文字目の状態から$l$のループを回して$i+1$文字目として"3"または"5"のときそれぞれの遷移を配るDPで行います。今回はサンプルより最大の文字列の長さが25とわかるので、$i=25$までのDPを求めておくことができます。

まずは$n$番目の数が何桁なのかを求めるために、$n$から$dp[i][j][0]$を小さいほうから順に引いていきます。そしてそれが0以下になるところ(小さいほうからの累積和が初めて$n$以上になるところ)が求める桁数になります。この結果は作問者の方の解説では数え上げによって求められていたものと同じです。

yukicoder294-1

桁数と先頭の数がわかったら、その中で$n'$番目の数は何なのかを求めます。上記の例では結局、4文字目が"5"で長さが4の条件を満たす文字列(2つある)の中で1番目の組み合わせを求めることになります。これは4文字目から1文字目までどのような遷移をたどってきたかを戻りながら求める$n'$番目の数を決定していきます。遷移を戻っていくためには決定した数字によって3で割った余りが変化していくところを考えていく必要があります。

yukicoder294-2

考察

この解説ではわかりやすいかと思って$i$文字目が$d[j]$("3"または"5")のときの組み合わせの数という状態を作りました。ちなみにuwiさんの回答では$j$に関する状態は作られていません($dp[i][k]$:$i$文字目までで各桁の数字の和を3で割った余りが$k$の組み合わせの数)。その代り$i$文字目がどちらなのかを決定する際にDPの$i-1$の値を使って決定されています。この解説では$i$文字目を決定するためにDPの$i$の値を使っています。結局やっていることは一緒だと思います。

問題概要

問題文はこちらを参照してください。

これも「AtCoder Typical DP Contest Q 連結」を考えているときに参考になった問題です。ほぼ、「SRM671 Div1 Easy BearCries」の解説と同じ内容で、情報量少なめです。

解法

「Q 連結」の解説で書いたように、この問題を下記と同じ考え方で解いていきます。

  • $i$文字目までの部分問題を使って、$i+1$文字目までの問題を解いている。
  • $i$文字目で考えられるすべての状態から、$i+1$文字目で起きうる状態へ配るDPで遷移している。
  • $i$文字目で考えるべき状態数は、問題の条件に依存する。
  • 求める解は$L$文字目で条件に合う状態の値をすべて足したもの。

まずは問題を「'A'~'Z'または'?'からなる長さ$L$の文字列において、"KUROI"の部分列に分解できる最大の個数を求めよ。」と言い換えてみます。('?'は'A'~'Z'のどれかに当てはまる)

この条件を判定するために必要なすべての状態についてですが、1文字ずつ文字を増やしていったときに、部分列は"K"だけ、"KU"、"KUR"と状態が変化をしていきます。これらの個数をカウントすることで全体の状態を管理していきます。

  1. "K"だけ(他の文字と組み合わさっていない)が$jk$個ある状態
  2. "KU"が$ju$個ある状態
  3. "KUR"が$jr$個ある状態
  4. "KURO"が$jo$個ある状態
  5. "KUROI"の状態の最大値

問題が部分列"KUROI"が最大何個できるのかなので、DPの値としてこの値を更新するようにします。つまり、5.の状態になったらDPの値を1増やすという遷移を考えます。'?'の場合は'K','U','R','O','I'のすべての可能性があるとして遷移させます。これら以外の文字は何もしません。

この問題も与えられた文字列によって状態の遷移先が決まっていきます。

漸化式の定義: $$\begin{array}{l} d=dp[i][jk][ju][jr][jo]とする\\ dp[i+1][jk+1][ju][jr][jo]=\max\{dp[i+1][jk+1][ju][jr][jo],\ d\}\\ \hfill (i+1文字目が'K'または'?'\land jk\lt 20)\\ dp[i+1][jk-1][ju+1][jr][jo]=\max\{dp[i+1][jk-1][ju+1][jr][jo],\ d\}\\ \hfill (i+1文字目が'U'または'?'\land ju\lt 20\land jk\gt 0)\\ dp[i+1][jk][ju-1][jr+1][jo]=\max\{dp[i+1][jk][ju-1][jr+1][jo],\ d\}\\ \hfill (i+1文字目が'R'または'?'\land jr\lt 20\land ju\gt 0)\\ dp[i+1][jk][ju][jr-1][jo+1]=\max\{dp[i+1][jk][ju][jr-1][jo+1],\ d\}\\ \hfill (i+1文字目が'O'または'?'\land jo\lt 20\land jr\gt 0)\\ dp[i+1][jk][ju][jr][jo-1]=\max\{dp[i+1][jk][ju][jr][jo-1],\ d+1\}\\ \hfill (i+1文字目が'I'または'?'\land jo\gt 0)\\ \end{array}$$

$dp[i][jk][ju][jr][jo]$:$i$文字目までの文字列を部分列に分割したときに、"K"のみのものが$jk$個あり、"KU"のものが$ju$個、"KUR"のものが$jr$個、"KURO"のものが$jo$個ある状態で"KUROI"ができている最大の数 $(0\le i\le L,\ 0\le jk,ju,jr,jo\le 20)$

$L$:文字列の長さ

初期値:$dp[0][0][0][0][0]=0$、それ以外は$-INF$(適切な負の値)

求める解:$\max\{dp[i][jk][ju][jr][jo]\}$(すべての値の中の最大の数)

「SRM671 Div1 Easy BearCries」と違って、

  • 求めるものが組合せの数ではなく、最終形の"KUROI"になる最大の数である。なので、初期値として$-INF$で初期化が必要。
  • ワイルドカードの'?'が含まれている。なので、解が最大になるように遷移が追加される。
などがあげられますが、基本的な流れは同じ問題と思います。

また、この問題は解説にもあるように次の点に注意が必要です。

  • 全体の文字列の長さから"KUROI"は最大20個しかできないので、各文字の状態の管理の上限を20にしても構わない。(だからTLEしない)
  • 遷移を発生させない関係ない文字のときは、$i$のときの値が$i+1$のときに移っていかないので、DPの領域を再利用するか、関係ない文字のときも$i$から$i+1$のときに値を遷移させる($dp[i+1][jk][ju][jr][jo]=dp[i][jk][ju][jr][jo]$)必要がある。

考察

後で考えると分かるんですけどね。本番では$100^5$になって間に合わないと思っていました。

問題概要

問題文はこちらを参照してください。

詳細な解説を作問者の方が既に書かれているので、気になったところだけ書きます。

考察

  1. インディケータ確率変数

    求めたい期待値の確率変数を、期待値の線形性を使って$X\{2\}$などの和で表しています。この1つの数字について生き残れば1、生き残らなければ0という確率変数を定義することで、結局確率を求めればよいとなっています。このような確率変数はインディケータ確率変数という名前で参考書籍で紹介している「数学ガール 乱択アルゴリズム」の中に出てきます。

  2. 条件付き確率

    「2 によって消されない」かつ「3 によって消されない」かつ「4 によって消されない」確率の説明の部分が直感的にわかりませんでした。

    「2 によって消されない」を事象$A$、「3 によって消されない」を事象$B$、「4 によって消されない」を事象$C$とすると、求める確率は$\Pr\{A\cap B\cap C\}$です。ここで条件付確率の乗法定理によって次のようになります。

    $$\Pr\{A\cap B\cap C\}=\Pr\{A\}\cdot\Pr\{B|A\}\cdot\Pr\{C|A\cap B\}$$

    事象$A$と事象$C$が独立ではないので、ちょっとややこしくなっています。$\Pr\{A\}=1-p$、事象$A$と事象$B$は独立なので$\Pr\{B|A\}=\Pr\{B\}=1-p$となります。$\Pr\{C|A\cap B\}$は、事象$A$、$B$が起こったという条件の下での事象$C$(4によって消されない)の確率なので、これも単純に$1-p$になります(事象$A$の2によって消されていないのは前提なので)。

    ということで、結局1と自分自身を除いた約数の個数分$1-p$をかけたものが求める確率です。

    条件付き確率を持ち出したことで余計わかりにくくなった気もするのですが、なかなか直感的に理解できない部分なので、こういうところまで考えないとなんかもやもやが残ります。

    確率変数についても、これを持ち出すと難しく見えますが、実はとても素晴らしい概念だと思います。高校数学の時には全然理解できていませんでしたが、確率変数の概念はおすすめです。

問題概要

問題文はこちらを参照してください。

いわゆるコンプガチャ問題の変形だと思います。。

解法

種類が100種類ということなので、どの種類を持っているのかという状態の区別をすると無理というのがわかります(20個程度だとbitDPの可能性)。なので、状態として1枚以上持っている種類数、2枚以上持っている種類数などを考えて、1回の試行によって1枚以上持っている種類数が1増えるか2枚以上持っている種類数が1増えるという状態の変化を考えてみます。

ここで、求めたい期待値の確率変数を次のように定義します。

$X_{ijk}$:1枚以上持っている種類数が$i$、2枚以上持っている種類数が$j$、3枚以上持っている種類数が$k$としたときに、3枚以上持っている種類数が$n$になるまでにカードを買う回数。ただし、$i\ge j\ge k$が成り立つ

このように考えると、1回の試行によって0枚持っている種類を引く、1枚持っている種類を引く、2枚持っている種類を引く、3枚以上持っている種類を引くの4通りのケースが考えられるので、$X_{ijk}$の条件付き期待値をもとに、確率変数$\mathrm{E}[X_{ijk}|Y]$の確率分布を表で表します。

$\mathrm{E}[X_{ijk}|Y]$ $1+\mathrm{E}[X_{i+1jk}]$ $1+\mathrm{E}[X_{ij+1k}]$ $1+\mathrm{E}[X_{ijk+1}]$ $1+\mathrm{E}[X_{ijk}]$ 合計
確率 $\frac{n-i}{n}$ $\frac{i-j}{n}$ $\frac{j-k}{n}$ $\frac{k}{n}$ 1

結局、No.65の解説にあったように、条件付き期待値の公式から、求める期待値は次のようになります。

$$\begin{eqnarray} \mathrm{E}[X_{ijk}] & = & \mathrm{E}[\mathrm{E}[X_{ijk}|Y]]\\ & = & 1+\mathrm{E}[X_{i+1jk}])\frac{n-i}{n}+\mathrm{E}[X_{ij+1k}])\frac{i-j}{n}+\mathrm{E}[X_{ijk+1}])\frac{j-k}{n}+\mathrm{E}[X_{ijk}])\frac{k}{n} \end{eqnarray}$$

ただし、右辺にも$\mathrm{E}[X_{ijk}]$が出てきているので、その変形が必要となります。これをDPとしてまとめると次ようになります。

漸化式の定義: $$ \begin{eqnarray} dp[i][j][k] & = & \{1+dp[i+1][j][k]\cdot \frac{n-i}{n}+dp[i][j+1][k]\cdot \frac{i-j}{n}\\ & + & dp[i][j][k+1]\cdot \frac{j-k}{n}\}/\frac{n-k}{n}\ (i\lt n)\\ dp[i][j][k] & = & \{1+dp[i][j+1][k]\cdot \frac{i-j}{n}\\ & + & dp[i][j][k+1]\cdot \frac{j-k}{n}\}/\frac{n-k}{n}\ (i=n,\ j\lt n)\\ dp[i][j][k] & = & \{1+dp[i][j][k+1]\cdot \frac{j-k}{n}\}/\frac{n-k}{n}\ (i=n,\ j=n,\ k\lt n) \end{eqnarray}$$

$dp[i][j][k]$:1枚以上持っている種類数が$i$、2枚以上持っている種類数が$j$、3枚以上持っている種類数が$k$としたときに、3枚以上持っている種類数が$n$になるまでにカードを買う回数の期待値$(0\le k \le n,\ k\le j \le n,\ j\le i \le n)$

初期値:$dp[n][n][n]=0$

求める解:$dp[$最初の状態で1枚以上持っている種類数$][$最初の状態で2枚以上持っている種類数$][$最初の状態で3枚以上持っている種類数$]$

考察

x枚以上持っている種類数でまとめるのがすぐ思いつけるようになるのでしょうか。。。場数をどんだけこなすかなんですかね。

このページのトップヘ