问题描述
如果一个自然数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。
解答:
找规律找到头炸。。。。。。
无奈还是上网参考了大神的动态规划的代码
代码如下:
import java.util.Scanner;
class Main{
static int MOD=1000000007 ;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int k = sc.nextInt();
int l = sc.nextInt();
int dp[][] = new int[101][101]; //dp[i][j]表示i位数,最后一位是j的k好数的个数,其中f[i][j] = sum(f[i-1][j]);
for (int i = 0; i < k; i++) {
dp[1][i] = 1; //如果是一位数,在第一位上取i(i=[0,k-1])的情况就只有一种
}
for (int i = 2; i <=l; i++) { //两位数以上的判断
for (int j = 0; j < k; j++) {
for (int j2 = 0; j2 < k; j2++) {
if(j2 != j-1 && j2 != j+1){ //判断j2是否与j不相邻
dp[i][j] += dp[i-1][j2];
/*
* dp[i][j]表示在第i位上放j(j=[0,k-1])的所有情况的个数。
* 而此时的for循环中的dp[i-1][j2],表示在第i-1位上的数字,并[0,(k-1)]中寻找,若与j不相邻,则给dp[i][j]加上dp[i-1][j2]的数值。
* dp[i-1][j2]中的数值表示,前一位(也就是i-1位)上,在符合前后不相邻的情况下,该位数值为j2的所有情况的个数。
*/
dp[i][j] %= MOD; //由于最终要取余,所以此处取余不影响结果,
//此处直接取余是为了减小数值,加快运算
}
}
}
}
int sum = 0;
for (int i = 1; i < k; i++) {
sum+= dp[l][i];
sum %= MOD;
}
System.out.println(sum);
}
}
/*
* K好数,k = 4
位数 该位取值 前一位可取个数 计次(part) 合计 减去数目
1 0~k-1 4 0
2 0 k-1 Q10 = k-1 Q10+Q11+Q12+Q13 3 00 02 03 k-1
1 k-2 Q11 = k-2
2 k-2 Q12 = k-2
3 k-1 Q13 = k-1
3 0 k-1 0 2 3 Q20 = Q10 + Q12 + Q13 Q20+Q21+Q22+Q23 8 000,002,003;020,022;030,031,033
1 k-2 1 3 Q21 = Q11 + Q13 k-1 + k-2 + k-1
2 k-2 0 2 Q22 = Q10 + Q12
3 k-1 0 1 3 Q23 = Q10 + Q11 + Q13
4 0 k-1 Q30 = Q20 + Q22 + Q23 Q30+Q31+32+Q33 ? (k-1 + k-2 + k-1) + (k-1 + (k-2)) + (k-1 + k-2 + k-1)
1 k-2 1 3 Q31 = Q21 + Q23
2 k-2 0 2 Q32 = Q20 + Q22
k-1 k-1 Q33 = Q20 + Q21 + Q23
......
L
*/
找到一个通俗易懂的动态规划入门传送,大家可以学习一波。
点我传送