K好数
题目
问题描述
如果一个自然数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。
关于动态规划的小故事(特别值得一看)
https://blog.csdn.net/v_yang_guang_v/article/details/46686441
关于k好数的理解
https://blog.csdn.net/qq_41714549/article/details/87435089
题目理解
1.题目要求的是“L位K进制数中的K好数 的数目”。怎么理解?
首先,要知道K进制数它的取值范围为[0,K-1],如4进制只能取[0,3];16进制为[0,15]等。
其次,明白什么是“L位K进制数”。如:“2位4进制数”,它是指这个数是个两位数,其中个位数是4进制数(即从[0,3]中取一个数作为个位),十位数也是4进制数。同理,“3位7进制数”则指这个数是个3位数,其中个位、十位、百位都是7进制数。
最后,按K好数的要求(任意相邻的两位不是相邻的数字)统计就能得到结果。
2.题目中为啥给出“由于数很大……输出取模后的值”这一条件?
首先,要明白“取模运算只有对象是整数间时才等于取余运算”。
最后,在数据规范与约定中,我们知道1K100,1 L100。我们假设K取100,L也取100。那么在100位100进制数中不考虑100好数的情况下,粗略一算,它的数就有100的100次方。肯定超过了int,long long。这时题目告诉我们取模来减小我们的负担。(感谢啊)
————————————————
版权声明:本文为CSDN博主「小白鼠零号」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_41714549/article/details/87435089
解题思路
用dp[i][j]=dp[i][j]+dp[i-1][k]来做。解释一下:这里的i 代表所在的位数(i=0代表个位,i=1代表十位,以此类推)。j 代表取K进制数的一个数(如果是4进制数,那么j取[0,3]中的一个数)。k和j同一个意思。整个式子的意思是当前位置的数总数=当前位置的数的数目+前一个位置的数的总数。
以2位4进制数的4好数为例:
dp[1][0]=dp[1][0]+dp[0][k]; k取[0,3] // 十位为0时,添上个位所取得数,看是否满足K好数。结果:dp[1][0]存的是十位为0时的满足4好数的个数,即:1 1、1 3 两种情况。
dp[1][1]=dp[1][1]+dp[0][k]; //同上理解
dp[1][2]=dp[1][2]+dp[0][k];
dp[1][3]=dp[1][3]+dp[0][k];
————————————————
版权声明:本文为CSDN博主「小白鼠零号」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_41714549/article/details/87435089
自己按照上面的理解,画图,这样子方便理解
代码
import java.util.Scanner;
public class k好数 {
final static int Mod=1000000007;
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc=new Scanner(System.in);
int K=sc.nextInt();//输入K进制
int L=sc.nextInt();//输入L长度
int sum=0;
//横坐标是位数,纵坐标是进制
//表示l位以k结尾,从1号开始,k中表示1.2.3.···k-1
int[][] arr=new int[L+1][K];
for(int i=1;i<=L;i++){
for(int j=0;j<K;j++)
arr[i][j]=0;//先进行初始化
}
for(int i=0;i<K;i++){//使得第一行中,只有一位数的k好数为1,以K=4为例,0,1,2,3每个数都是只有1位的k好数
arr[1][i]=1;
}
for(int i=2;i<=L;i++){//每位
for(int j=0;j<K;j++){//每位中k的结尾,这说起来一点都不好理解,自己画图就理解了
for(int x=0;x<K;x++){
if(x!=j-1 && x!=j+1){//就是说不相邻
arr[i][j] += arr[i-1][x];//加上少一位的k的位数的值,先开始的初始值都为0;
arr[i][j] %=Mod;//进行余数计算
}
}
}
}
//把K=0的去掉,不加入sum的值
for(int j=1;j<K;j++){
sum +=arr[L][j];
sum%=Mod;
}
System.out.println(sum);
}
}