您的位置:首页 > 其它

蓝桥水题_算法训练 K好数

2018-01-05 16:18 309 查看
题目看了很久,都没看懂为什么“K = 4,L = 2的时候,所有K好数为11、13、20、22、30、31、33 共7个”,那“00、02、03”去哪了,问人才知道,这0开头的不算自然数。。。,因为自然数是0,2,3一位,不是两位,囧

一开始没想到是用动态规划,想的是用找规律或者暴力枚举,搞了很久没想出来思路,打开锦囊知道是DP,不过还是没思路。

网上看了别人的代码,琢磨了一下,其实原理就是以1位数作为基础,一步一步去推剩下的K位数包含几个好数

K = 4,L = 3时,比如dp[2][3]代表以3结尾的2位数中(K=4进制)有几个好数

则状态转移方程为:
dp[i][j] += dp[i-1][x] (未考虑取余)

第一步,将1到K-1结尾的一位数的包含好数值设为1(注意不从0开始,因为00,01不算自然数),因为1,2,3天然算好数

第二部,所以dp(2,1) = dp(1,1) + dp(1,3) ,因为x不能等于 0 和 2,这样一直带入

......

最后一步,将dp(L,0)到dp(L,3)累加,即最后的结果(未考虑取余)

代码:

#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
#include <stack>
#include <list>
#include <algorithm>
using namespace std;
#define MAX 101
#define MOD_NUM 1000000007

//dp(动态规划)数组的第一个数为位数,第二个数K进制
//(这也是一个坑点,题目应该是K < 10^6,但实测开不了那么大,不过不影响提交)
//K = 4,L = 2时,dp[2][3]代表以3结尾的2位数中(K=4进制)有几个好数
unsigned long long dp[MAX][200000];

int main() {
unsigned long long K = 0,L = 0;
cin>>K>>L;

for(int i = 1 ; i < K ; ++i) {
//初始化,这个想了很久,这题是从一位数开始考虑的
//之所以不从0开始,是因为类似 00,01,002这些数不算自然数,
//其他的数比如1、22、333这些必是好数,所以在1位时,1,2,3这些数作为基础
dp[1][i] = 1;
// printf("dp[1][%d] = 1;\n",i);
}

// cout<<endl;

//这里因为提交的时候L写成K卡了好久,一直90分,囧
for(int i = 2 ; i <= L ; ++i) {
for(unsigned long long j = 0 ; j < K ; ++j) {
for(unsigned long long x = 0 ; x < K ; ++x) {
//题目,任意的相邻的两位都不是相邻的数字
if(x!=j-1 && x!= j+1) {
//状态转移方程,这题的核心
//这里不能用+=,只能一步一步的取余,且必须要提前取余,降低数字大小
//这里的原理建议自己拿出纸笔,自己算
//比如:dp(2,0) = dp(1,0) +dp(1,1) +dp(1,3)
//因为 j = 0 , 则x不能相邻,即等于-1或1
//同理:dp(2,1) = dp(1,1,) + dp(1,3) ,因为x不能等于 0 和 2
dp[i][j] = (dp[i][j]+dp[i-1][x])%MOD_NUM;
// printf("dp[%d][%d] = (dp[%d][%d]+dp[%d-1][%d])%MOD_NUM = %d;\n",i,j,i,j,i,x,dp[i][j]);

}
}
}
}

// cout<<endl;

unsigned long long ans = 0;
for(int i = 0 ; i < K ; ++i) {
//把最高长度位的全加在一块
ans = (ans+dp[L][i]) %MOD_NUM;
// printf("ans = (ans+dp[%d][%d]) %MOD_NUM = %d ;\n",L,i,ans);
}

cout<<ans;

return 0;
}

建议把注释的printf解掉,看看调试过程
比如K = 4,L = 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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: