トピック
LCP 25. アンティークキーボード
シャオコウさんは秋のマーケットでアンティークのキーボードを買いました。アンティークキーボードは老朽化しているため、キーボード上で押せる文字は a ~ z の 26 文字のみで、各文字は最大でも k 回しか押すことができません。
シャオコウはランダムにボタンを n 回押しました。シャオコウが押せるコンテンツの総数を返してください。数値が大きいため、最終的な答えには 1000000007 (1e9 + 7) を法とする必要があります。
例 1:
输入:k = 1, n = 1
输出:26
解释:由于只能按一次按键,所有可能的字符串为 "a", "b", ... "z"
例 2:
输入:k = 1, n = 2
输出:650
解释:由于只能按两次按键,且每个键最多只能按一次,所有可能的字符串(按字典序排序)为 "ab", "ac", ... "zy"
ヒント:
1 <= k <= 5
1 <= n <= 26*k
答え
動的プログラミング:
- dp[i][j] を使用して、最初の j 文字を使用して押すことができる長さ i の文字列の総数を表します。j 番目の文字が x 回押されたとします (x の値の範囲は 0 ~ k)。
C(i, x) は、i 位置の中から x 位置を選択する方法が何通りあるかを示します。 - C(n,m)の計算方法:
C++ コード
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll mod = 1000000007;
class Solution {
public:
int keyboard(int k, int n) {
vector<vector<ll>> dp(n + 1, vector<ll>(27, 0L));
for (int j = 0; j <= 26; ++j) {
dp[0][j] = 1;
}
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= 26; ++j) {
for (int x = 0; x <= k; ++x) {
if (i >= x) {
dp[i][j] += dp[i - x][j - 1] * C(i, x);
}
}
dp[i][j] %= mod;
// cout << i << "," << j << ":" << dp[i][j] << endl;
}
}
return dp[n][26];
}
ll C(int n, int m)
{
ll fz = 1;
ll fm = 1;
for (int i = n; i >= n - m + 1; --i) {
fz *= i;
}
for (int j = m; j >= 2; --j) {
fm *= j;
}
return fz / fm;
}
};