算法训练 K好数
@蓝桥杯 算法训练 ALGO-3
问题描述
如果一个自然数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 = 4,L = 3)以3结尾的数个数时,
你只需知道(K = 4,L = 2)满足以结尾3的数的个数,也就是以0,1,3结尾的数的个数。
根据题目描述已知这种数有:20、30、11、31、22 、13、33 2、2、1 、2个
也就是以3结尾的数有:113、133、203、303、313、333 2 + 2 + 2 = 6个
同理,以2结尾的数有:202、222、302
以1结尾的数有:111、131、311、331
以0结尾的数有:130、200、220、300、330
(K = 4,L = 3) 共 18 个K好数。
在这个思路里,L=2的解在L=3时是可以沿用的。
以上主要解明我理解的动态规划,和解题流程有一定出入,还望周知。
但是这道题正推很麻烦 ,首先我没有往这个方向想 ,因为题目没有把不足位补0的数计在K好数总和内,所以我选择反向结合。
求 K = 4,L = 3 解:
得 5 + 5 + 8 = 18,问题规模扩大,以此类推。
用HTML画的图,有一说一,不好用。。。
想解释一下为什么结果集第一层填1,但我觉得没这个必要,告辞。
源码:
import java.util.Scanner;
public class Main {
static final int mod = 1000000007;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int k = sc.nextInt(), l = sc.nextInt();
long sum = 0;
long[][] dp = new long[l][k];
for (int i = 0; i < k; i++)
dp[0][i] = 1;
for (int i = 1; i < l; i++)
for (int j = 0; j < k; j++)
for (int p = 0; p < k; p++)
if (Math.abs(p - j) != 1) dp[i][j] += dp[i - 1][p] % mod;
for (int i = 1; i < k; i++)
sum += dp[l - 1][i];
System.out.println(sum % mod);
}
}