篮桥杯 - K好数

篮桥杯 - 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。

思路

动态规划

就是一个二维数组,行位数,列表示进制。进制能填的数是从:0 - K-1, 位数能填的数是从:1 - L 位。
A[i][j] 的意义是:当前是 i位数,这一位数如果填入 j, 一共有多少种填法?要知道,当前填入这个数,其实是和上一位数是有关系的。如果当前填 2, 那么前一位填就不能是:1,3。所以需要把:除 A[i][1], A[i][3] 上的所有数加起来填入 A[i][2],这就是当前i位填 2,能有多少种填法。
注意:因为最前面一位不能为0,所以最终在算结果的时候需要排除 A[L][0] 这种情况,你可能觉得 L不是最后一位吗?是的,但是如果一开始就考虑 第一位为0的情况是不好做得,所以不妨讲数字倒着看,讲L位作为 第一位,1为最后一位,这样就好理解了。

篮桥杯 - K好数_第1张图片

代码:

#include <bits/stdc++.h>

using namespace std;

int main()
{
    int K,L;
    int A[101][101] = {0};

    while(cin>>K>>L)
    {
        for(int j=0; j<K; ++j)
        {
            A[1][j] = 1;
        }

        for(int i=2; i<=L; ++i){
            for(int j=0; j<K;++j){
                A[i][j] = 0;
                for(int x=0; x<K; ++x){
                    if(x != j-1 && x!=j+1){
                        A[i][j] += A[i-1][x];
                        A[i][j] %= 1000000007;
                    }
                }
            }
        }

        int result = 0;
        // 可以将L位看作第一位,所以当第一位为0时这个数是无效的,所以从1开始加
        // 最后这个数是倒着的
        for(int j=1; j<K; ++j){
            result += A[L][j];
            result %= 1000000007;
        }

        cout<<result<<endl;
    }
    return 0;
}

你可能感兴趣的:(篮桥杯 - K好数)