Leetcode-LCP 25. 古董键盘

题目

LCP 25. 古董键盘

小扣在秋日市集购买了一个古董键盘。由于古董键盘年久失修,键盘上只有 26 个字母 a~z 可以按下,且每个字母最多仅能被按 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]表示长度为i,使用前j个字母能按出的字串总数。假设第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;
    }
};

猜你喜欢

转载自blog.csdn.net/weixin_36313227/article/details/126794462
今日推荐