如果一个自然数N的K进制表示中任意的相邻的两位都不是相邻的数字,那么我们就说这个数是K好数。求L位K进制数中K好数的数目。例如K = 4,L = 2的时候,所有K好数为11、13、20、22、30、31、33 共7个。由于这个数目很大,请你输出它对1000000007取模后的值。
输入包含两个正整数,K和L。
对于30%的数据,K^L <= 10^6;
对于50%的数据,K <= 16, L <= 10;
对于100%的数据,1 <= K,L <= 100。
参考自https://www.cnblogs.com/chunzhulovefeiyue/p/6666291.html
https://blog.csdn.net/qq_35875420/article/details/59676296
https://blog.csdn.net/zuzhiang/article/details/78722486
参考的很多,综合了各路大神的想法,结合自己的理解。
大佬的解题思路:K进制的意思是它每一位的组成只能从(0~K-1)中选取,如果想直接求L位长的K进制数有多少K好数,可能有些复杂,不如先求1位长,再通过1位长求2位长……以此类推,便可以通过累加得出L位长的K好数总共有多少。
先分析下样例,k=4,l=2即表示二位的四进制数,最高位不能是0,否则就不是二位数字了,比如数字0867应该是三位数字而不是四位。
所有情况共有10,11,12,13,20,21,22,23,30,31,32,33.
10 因为1和0是相邻的数字,所以10不是K好数,同理12、21、23,32也不是k好数。所以k好数一共7个。
dp[i][j]的i表示位数,j表示该位数下最后一位的数字,dp[i][j]的值为位数是i,最后一位数字是j的K好数的个数。
当i=1时,也就是长度是1时,所有的数字都是K好数,因为没有数字相邻的情况。
状态转移方程:dp[i][j] = sum( dp[i-1][x] ) 其中 sum 是求和,x != j-1 且 x != j+1。即:i位数最后一位是j的所有数字=i-1位数且最后一位数字不和j相邻的所有情况相加。
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N = 110, mod = 1000000007; 4 int dp[N][N]; 5 int main() { 6 int k, l; //k是进制,l是位数 7 cin >> k >> l; 8 for (int j = 0; j < k; j++) { //所有一位数字,最后一位是j的k好数个数为1 9 dp[1][j] = 1; 10 } 11 for (int i = 2; i <= l; i++) { //从两位开始算 12 for (int j = 0; j < k; j++) { //每一位可以是o~k-1 13 for (int x = 0; x < k; x++) { 14 if (x != j - 1 && x != j + 1) { //若i-1位数的最后一位x不与j相邻 15 dp[i][j] = (dp[i][j] % mod + dp[i - 1][x] % mod) % mod; 16 } 17 } 18 } 19 } 20 int ans = 0; 21 for (int j = 1; j < k; j++) { 22 ans = (ans % mod + dp[l][j] % mod) % mod; 23 } 24 cout << ans << endl; 25 return 0; 26 }