topic
LCP 25. Antique Keyboard
Xiaokou bought an antique keyboard at the autumn market. Due to the antique keyboard being in disrepair, there are only 26 letters a~z that can be pressed on the keyboard, and each letter can only be pressed k times at most.
Xiaokou pressed the button n times randomly. Please return the total number of contents that Xiaokou can press. Because of the large number, the final answer requires modulo 1000000007 (1e9 + 7).
Example 1:
输入:k = 1, n = 1
输出:26
解释:由于只能按一次按键,所有可能的字符串为 "a", "b", ... "z"
Example 2:
输入:k = 1, n = 2
输出:650
解释:由于只能按两次按键,且每个键最多只能按一次,所有可能的字符串(按字典序排序)为 "ab", "ac", ... "zy"
hint:
1 <= k <= 5
1 <= n <= 26*k
answer
Dynamic programming:
- Use dp[i][j] to represent the total number of strings of length i that can be pressed using the first j letters. Assume that the j-th letter is pressed x times (the value range of x is 0~k), then:
C(i, x) indicates how many ways there are to select x positions among i positions. - C(n,m) calculation method:
C++ code
#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;
}
};