蓝桥杯 K好数(DP)

问题描述

如果一个自然数N的K进制表示中任意的相邻的两位都不是相邻的数字,那么我们就说这个数是K好数。求L位K进制数中K好数的数目。例如K = 4,L = 2的时候,所有K好数为11、13、20、22、30、31、33 共7个。由于这个数目很大,请你输出它对1000000007取模后的值。

输入格式

输入包含两个正整数,K和L。

输出格式
输出一个整数,表示答案对1000000007取模后的值。
样例输入
4 2
样例输出
7
数据规模与约定

对于30%的数据,KL <= 106

对于50%的数据,K <= 16, L <= 10;

对于100%的数据,1 <= K,L <= 100。

 

 

简单DP,dp[i][j],其中i代表的是数字有几位,j代表首位放j的情况有几种

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define mod 1000000007
__int64 dp[105][105];

int main()
{
    int k,l,i,j,x;
    scanf("%d%d",&k,&l);
    for(i = 0; i<k; i++)
        dp[1][i] = 1;
    for(i = 2; i<=l; i++)
        for(j = 0; j<k; j++)
            for(x = 0; x<k; x++)
                if(x!=j-1&&x!=j+1)//根据题意,本位的数字与前面的数字是不能相邻的
                {
                    dp[i][j]+=dp[i-1][x];
                    dp[i][j]%=mod;
                }
    __int64 sum = 0;
    for(i = 1; i<k; i++)
    {
        sum+=dp[l][i];
        sum%=mod;
    }
    printf("%I64d\n",sum%mod);

    return 0;
}




 

### 蓝桥杯动态规划问题概述 动态规划(Dynamic Programming, DP)是一种常用的算法设计技术,适用于具有重叠子问题和最优子结构性质的问题。以下是关于蓝桥杯中常见动态规划问题的解题思路及相关知识点。 #### 动态规划的核心要素 动态规划主要依赖于两个核心特性: 1. **最优子结构**:一个问题的最优解可以通过其子问题的最优解构建而成[^2]。 2. **重叠子问题**:在求解过程中,许多子问题是重复出现的,因此可以缓存这些子问题的结果以提高效率[^3]。 #### 动态规划的一般流程 - 定义状态变量并初始化边界条件。 - 寻找状态转移方程,这是解决问题的关键部分。 - 使用迭代或记忆化递归的方式填充状态表。 - 输出最终结果。 --- ### 示例题目解析 #### 题目描述 假设有一道典型的蓝桥杯动态规划题目如下: > 给定一个长度为 `n` 的整组 `arr` 和一个正整 `k`,找出其中连续子组的最大和不超过 `k` 的最大可能值。如果不存在这样的子组,则返回 `-1`。 #### 输入输出要求 - 输入:第一行为测试用例量 `T`;对于每个测试用例,第一行包含两个整 `n` 和 `k`,第二行为 `n` 个整表示组 `arr`。 - 输出:对于每个测试用例,输出满足条件的最大子组和。 #### 解题思路 此问题可以用滑动窗口配合前缀和的思想来优化暴力枚举的方法,也可以通过动态规划解决。以下是基于动态规划的状态定义与转移方程: 1. **状态定义** 设 `dp[i][j]` 表示从第 `i` 个元素到第 `j` 个元素构成的子组的最大和,且该和不超过 `k`。 2. **初始条件** 对于单个元素的情况,即当 `i == j` 时,`dp[i][i] = arr[i]` 如果它小于等于 `k`,否则设为负无穷大。 3. **状态转移方程** 当考虑多个元素组成的子组时,有以下关系: \[ dp[i][j] = \begin{cases} max(dp[i][j-1], sum(i,j)) &\text{if } sum(i,j) \leq k \\ -\infty &\text{otherwise} \end{cases} \] 4. **时间复杂度分析** 此方法的时间复杂度为 \(O(n^2)\),适合中小规模据集。若需进一步优化,可引入单调队列或其他技巧降低复杂度至线性级别。 #### Python 实现代码 ```python def max_subarray_sum(arr, n, k): # 初始化前缀和组 prefix_sum = [0] * (n + 1) for i in range(1, n + 1): prefix_sum[i] = prefix_sum[i - 1] + arr[i - 1] result = -float('inf') deque = [] for j in range(n + 1): while deque and prefix_sum[j] - prefix_sum[deque[0]] > k: deque.pop(0) if deque: current_sum = prefix_sum[j] - prefix_sum[deque[0]] result = max(result, current_sum) while deque and prefix_sum[j] <= prefix_sum[deque[-1]]: deque.pop() deque.append(j) return result if result != -float('inf') else -1 # 测试样例 test_cases = int(input()) for _ in range(test_cases): n, k = map(int, input().split()) arr = list(map(int, input().split())) print(max_subarray_sum(arr, n, k)) ``` 上述代码实现了更高效的解决方案,采用双端队列维护最小前缀和索引来快速更新候选答案。 --- ### 总结 动态规划作为一种强大的工具,在处理涉及最优化、计问题时非常有效。针对蓝桥杯中的具体题目,合理选择状态定义方式以及推导清晰的状态转移方程至关重要。此外,还需注意边界情况及性能调优策略的应用。
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值