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
可以列出表格寻找规律

j 0 1 2 3 k-1
i=1 1 1 1 1 1 1
i=2 k-1 k-2 k-2 k-2 k-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 这样我们就可以求出位数为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 评测详情

你可能感兴趣的:(蓝桥杯,练习系统,java,动态规划,算法)