如果一个自然数N的K进制表示中任意的相邻的两位都不是相邻的数字,那么我们就说这个数是K好数。求L位K进制数中K好数的数目。例如K = 4,L = 2的时候,所有K好数为11、13、20、22、30、31、33 共7个。由于这个数目很大,请你输出它对1000000007取模后的值。
输入包含两个正整数,K和L。
对于30%的数据,KL <= 106;
对于50%的数据,K <= 16, L <= 10;
对于100%的数据,1 <= K,L <= 100。
这道题对我而言真的有难度,嗯,思路卡在了如何应对L的变化问题,感到无从下手,上网学习了别人的算法,代码如下:
#include<stdio.h>
#include<math.h>
int num[100][100];
int main()
{
int K, L;
int i, j, m;
int sum;
scanf("%d%d",&K,&L);
for( i = 0; i < K; ++i ){
num[1][i] = 1;
}
for( i = 2; i <= L; ++i ){
for( j = 0; j < K; ++j ){
for( m = 0; m < K; ++m ){
if( abs(m - j) != 1 ){
num[i][j] = num[i][j] + num[i-1][m];
}
}
}
}
sum = 0;
for( i = 1; i < K; ++i ){
sum = (sum + num[L][i]) % 1000000007;
}
printf("%d\n",sum);
return 0;
}
但是在一开始理解上还是有些困难,没有清楚理解m的用意,可以这么想,比如,我们进行到了第三位的2这种情况(即i=3,j=2时),那么我们想找找有多少种情况可以让这个第三位上的数是二,无非只需要看看第二位上的数等于几,能让第三位上的数在不违背题意的前提下成立,那么肯定很容易知道,第二位上的数可以等于0,4(假定K=5),也就是说,我们有0和4这两种到达i=3,j=2的办法,但是,到达0和4的办法又不是单一的,比如到达0有a种方法,到达4有b种方法,所以我们需要一个累加的过程,所以到达i=3,j=2的情况,应该是到达i=2,j=0和i=2,j=4这两种情况的方法数之和(a+b种),所以也就可以理解为什么有m了,也就是找到在上一位数中满足条件的数,同时,再把到达相应满足条件的数的情况数加起来,如此往复,加到最后一位,此时,最后一位的任何一种情况的到达的情况总数你都已经累加起来了,注意,最后一位是最高位,不能为0哒,所以最后那个for循环从1开始。
还有个问题当时也不理解,当定义数组的时候,如果我把int num[100][100]写在主函数里面,那么结果是一个乱七八糟的数,如果写在主函数外面,则是答案,虽然明白是局部变量和全局变量的原因,但是仍然不够细,后来明白,当是定义在所有函数以外的变量或数组时,编译时会自动将所有值都初始化为0.声明在主函数中的变量或数组是局部性质的,在没有为其赋初值时它们的值是机器垃圾值(感谢百度知道的大神指点)。
就这样吧