蓝桥杯 K好数

问题描述

如果一个自然数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。


这道题对我而言真的有难度,嗯,思路卡在了如何应对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.声明在主函数中的变量或数组是局部性质的,在没有为其赋初值时它们的值是机器垃圾值(感谢百度知道的大神指点)。

就这样吧

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值