问题描述
如果一个自然数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
算法思路
1位4好数就是这个数本身了:1,2,3。
2位4进制数有10,11,12,13,20,21,22,23,30,31,32,33,符合4好数的数有11,13,20,22,30,31,33 共7个。
那3位4进制4好数就有111,113,130,131,133,200,202,203,220,222,300,302,303,311,313,330,331,333 共18个。
从上面可以看出2位4好数可以由1位4好数的结果推出,3位4好数可以由2位4好数的结果推出,那么4位4好数的结果也可以由3位4好数的结果推出。
1位4好数 --> 2位4好数
1 --> 11、13
2 --> 20、22
3 --> 30、31、33
2位4好数 --> 3位4好数
11 --> 111、113
13 --> 130、131、133
20 --> 200、202、203
22 --> 220、222
30 --> 300、302、303
31 --> 311、313
33 --> 330、331、333
L位数时,那我们只要确定第一位数,第二位数不与第一位数相邻,第三位数不与第二位数相邻……用array[i] [j] = array[i] [j] + array[i-1] [k] 来做。
示例代码
import java.util.Scanner;
public class Main{
final static int num = 1000000007;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int k = scanner.nextInt();
int l = scanner.nextInt();
int sum = 0;
// dp[i][j]中的i表示k好数的位数(i>0),j表示k的范围[0, k-1]
// dp[i][j]表示i位k好数第i位以j开头的k好数的个数
// 例如:k=4, l=3时:
// dp[1][1]表示第1位以1开头的k好数的个数,这个数只有1本身,
// 故dp[1][1]=1,且dp[1][2]=dp[1][3]=1。
// dp[2][1]表示第2位以1开头的k好数的个数,这个数有11、13,
// 故dp[2][1]=dp[1][1]+dp[1][3]。同理,dp[2][0]=dp[1][0]+dp[1][2],dp[2][2]=dp[1][0]+dp[1][2]
// dp[3][2]表示第3位以2开头的k好数的个数,这个数有20_、22_,_表示任意与上一位不相邻的数,
// 故dp[3][2]=dp[2][0]+dp[2][2]。
int[][] dp = new int[l + 1][k];
// 初始赋值全为0
for(int i = 0; i < l + 1; i ++){
for(int j = 0; j < k; j ++){
dp[i][j] = 0;
}
}
for(int i = 0; i < k; i ++){
dp[1][i] = 1;
}
for(int i = 1; i < l + 1; i ++){
for(int j = 0; j < k; j ++){
for(int m = 0; m < k; m ++){
if(Math.abs(m - j) != 1){
dp[i][j] += dp[i - 1][m];
dp[i][j] %= num;
}
}
}
}
for(int i = 1; i < k; i ++){
sum += dp[l][i];
sum %= num;
}
System.out.print(sum);
scanner.close();
}
}