[AtCoder] ABC 178 C – Ubiquity
問題
方針
組み合わせ
全ての数列の組み合わせは \( 10^N \) 個あります。\( 0 \) または \( 9 \) が存在しない数列の組合せは \( 9^N \) 個あります。\( 0 \) と \( 9 \) が存在しない数列の組み合わせは \( 8^N \) 個あります。
ここで、全ての組み合わせの集合を \( U \)、\( 0 \) が存在しない集合を \( A \)、\( 9 \) が存在しない集合を \( B \) とすると、求める集合は、
\[ U – A – B + A \cap B\]
となります。したがって、求めるものは
\[ 10^N – 2 \times 9^N + 8^N\]
となります。
動的計画法
ここで、配列 \( d \) を次のように定義します。
- \( d(i, 0)\) : \( i \) 個の整数列で \( 0 \) と \( 9 \) を含まないものの個数
- \( d(i, 0)\) : \( i \) 個の整数列で \( 0 \) を含まないものの個数
- \( d(i, 0)\) : \( i \) 個の整数列で \( 9 \) を含まないものの個数
- \( d(i, 0)\) : \( i \) 個の整数列で \( 0 \) と \( 9 \) を含むものの個数
初期値は \( d(0, 0) = 1 \) とし、更新式は、
\begin{eqnarray}
d(i + 1, 0)&=& 8d(i, 0)\\
d(i + 1, 1)&=& d(i, 0) + 9d(i, 1)\\
d(i + 1, 2)&=& d(i, 0) + 9d(i, 2)\\
d(i + 1, 3)&=& d(i, 1) + d(i, 2) + 10d(i, 3)
\end{eqnarray}
となります。したがって、\( d(N, 3) \) が答えです。
コード
組み合わせ
#include <bits/stdc++.h> using namespace std; typedef long long ll; ll mod = pow(10, 9) + 7; ll modpow(ll a, ll n) { if (mod <= 0) return 0; ll res = 1; while (n > 0) { if (n & 1) res = res * a % mod; a = a * a % mod; n >>= 1; } return res; } int main() { ll N; cin >> N; ll ans = modpow(10, N) - 2 * modpow(9, N) + modpow(8, N); ans = (ans + mod * 100) % mod; cout << ans << "\n"; return 0; }
動的計画法
#include <bits/stdc++.h> using namespace std; typedef long long ll; ll dp[1000001][4]{}; int main() { int N; cin >> N; ll mod = pow(10, 9) + 7; dp[0][0] = 1; for (int i = 0; i < N; i++) { dp[i + 1][0] = dp[i][0] * 8; dp[i + 1][1] = dp[i][0] + dp[i][1] * 9; dp[i + 1][2] = dp[i][0] + dp[i][2] * 9; dp[i + 1][3] = dp[i][3] * 10 + dp[i][1] + dp[i][2]; for (int j = 0; j < 4; j++) { dp[i + 1][j] %= mod; } } cout << dp[N][3] << "\n"; return 0; }
感想
これ解けなくてちょびっと涙が出た。
ディスカッション
コメント一覧
まだ、コメントがありません