现在的位置: 首页 > 综合 > 正文

蓝桥杯 – 算法训练 – ALGO – 3 K好数

2017年10月18日 ⁄ 综合 ⁄ 共 1125字 ⁄ 字号 评论关闭

小记: 上午盯着看了, 由于没注意看题目类型,所以不晓得是用动态规划,于是作死的从各方面想, 先是从数论方面,然后找规律,最后证实都不可行,期间 真的是很想很想 直接百度一下看看别人的思想, 但是想想,觉得这类题 就是一种分界线, 不能靠别人。 于是 再整理好思绪 认真分析, 然后 思路立马就出来了。。唉~ 天意啊, 以后认认真真做题, 坚决不搜题解,只在 代码有问题, 想和别人交流思想的情况下,再去搜题解,那样的效果最好。

思路:L位K进制,都是100 的数量级, 暴力肯定直接pass, 规律,寻不到(寻得到的 都是大神). 认真分析,对于每一位数, 如果不是最高位,那么都可以用0到k-1这k个数来填充这一位,对于填充的每一位,我们假定已经知道如果这一位填充它的话,那么好数会有f[i][j] 个(i表示第i位,j表示填的数),那么 我们将0-k-1这k个数的f[i][j]的值 全部相加起来最后得到的肯定是我们所要的答案(对于最高位为0,我们会另行判断,这里是假设),于是这里满足了dp的最优化原理,而对于第i位的数字,它的求值是无后效性的,因为结果只是相加,所以dp的无后效性也满足了,那么就可以用dp来做。

然后现在就是状态转移方程,f[i][j] = ∑f[i-1][r] (r != j±1 ,0<=r < k, i > 1)初始化f[1][j] = 1 (0<= j < k);

状态方程对最高位要特殊处理,因为最高位不能为0.

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

const int MAX_ = 101;
const int M = 1000000007;

int f[MAX_][MAX_];

int main() {
    int l, k;
    long long ans, n;

    while(cin >> k>> l) {
        if(l == 1){
            cout<<k-1<<endl;
            continue;
        }
        memset(f,0,sizeof(f));
        for(int j = 0; j < k; ++j) {
            f[1][j] = 1;
        }
        for(int i = 2; i < l; ++i) {
            for(int j = 0; j < k; ++j) {
                int cnt = 0;
                for(int r = 0; r < k; ++r) {
                    if(r == j + 1 ||r == j - 1)continue;
                    cnt = (cnt + f[i-1][r]) % M;
                }
                f[i][j] = cnt;
            }
        }
        int sum = 0;
        for(int j = 1; j < k; ++j) {
            int cnt = 0;
            for(int r = 0; r < k; ++r) {
                if(r == j + 1 ||r == j - 1)continue;
                cnt = (cnt + f[l-1][r]) % M;
            }
            sum = (sum + cnt)%M;
        }
        cout<< sum <<endl;
    }
    return 0;
}

抱歉!评论已关闭.