k好数——窥得动态规划思想

K好数

资源限制
时间限制:1.0s 内存限制:256.0MB
问题描述
如果一个自然数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。

思路

首先蓝桥杯对这道题解决方案的关键字是动态规划
对于初学者的我就要去了解什么是动态规划,如何取用动态规划的思想去解决问题,浏览几篇相关博客后,然后开始着手这道题目
我眼中的动态规划:一个有着多个阶段的最优决策问题。要解决的问题首先是可以划分成多个状态,选择一个状态作为初始状态,每一个状态与上一个状态之间都有一定的联系,即根据状态转移方程来实现状态的转移,最后达到最终状态求得最优解
对于这道题目来说:
弄清楚k好数的定义,k好数的个数取决于数的位数和进制,任意相邻的两位不能是相邻的数字
初始化一个二维数组int dp[i+1][k] (这里考虑到的是位数是从1开始的,所以有i+1的出现,方便数组定义)
求l为k进制k好数的数目,我们用一个二维数组来表示初始的状态dp[i][j]表示一个i位数首字母为j的k好数
首先有一点对于位数为1,进制为k的数,dp[1][j]始终为1
可以列出表格寻找规律

j0123k-1
i=1111111
i=2k-1k-2k-2k-2k-1
i=3(k1)2+(k-2)(k-2)

这里主要是dp[3][0]作为例子
首位为0下一位有k-1中取值情况
第二位为0和k-1的时候,特殊情况,发现第三位可以取(k-1)
第二位为其他情况时,第三位有(k-2)中取法
最后dp[3][0]=(k-1)2+(k-2)(k-2)
那么结合表格就可以找出规律,从而写出状态转移方程了
dp[i][j]+=dp[i-1][p] 0<p<k
这样我们就可以求出位数为i首位为j的k好数了
然后题目的要求其实就是求dp[l][]
通过循环实现dp[l][j]就可以求出k好数的个数,再对1000000007取模

代码实现

import java.util.Scanner;

public class KNumber {
	public static void main(String[] args){
		Scanner scanner=new Scanner(System.in);
		int k,l,sum=0;
		k=scanner.nextInt();
		l=scanner.nextInt();
		int dp[][]=new int[l+1][k];
		final int mod=1000000007;
		for(int j=0;j<k;j++){
			dp[1][j]=1; 
		}		for(int i=2;i<=l;i++){
			for(int j=0;j<k;j++){
				for(int p=0;p<k;p++){
					if(Math.abs(j-p)!=1){
						dp[i][j]+=dp[i-1][p];
					}
				}
			}
		}
		for(int m=1;m<k;m++){
			sum+=dp[l][m];
		}
		System.out.print(sum%mod);
	}
}

总结

通过这道算法训练题目有一定的收获,对动态规划的思想解决问题有了一定的认识,最后正确率只有百分之40的原因可能我对题目中的数据取模与约定没有完全地实现(只考虑了主要的动态规划的部分),以后如果能解决这个问题,就会修改代码。

K好数 07-13 09:08 526B JAVA 错误 40 140ms 22.10MB 评测详情

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值