zoukankan      html  css  js  c++  java
  • 题解-ABC161D Lunlun Number

    D - Lunlun Number

    此题本人是用 (dp+构造) 做的。

    (dp[i][j]) 代表以 (i) 开头,有 (j) 位的lunlun数有多少个。

    根据样例的提示,其实 (j) 最大也就 (10)(i)([0,9])

    首先初始化所有 (dp[i][1]=1)

    然后不难想到转移方程 (dp[i][j]=dp[i-1][j-1]+dp[i][j-1]+dp[i+1][j-1])

    当然如果 (i=0或i=9) 时要特殊处理(具体见代码)。

    接下来开始构造。

    首先算出第 (k) 个数的位数。

    这很好办,我们只用统计每个位数有多少lunlun数,然后做一遍前缀和,从小到大遍历,找到第一个大于等于 (k) 的位数即为 (k) 的位数。

    确定好位数之后我们就可以开始枚举每一位是什么了。

    当然不是暴力枚举。

    如果是第一位,我们暴力枚举 (1-9),用找位数同样的方法,我们可一个确定第一个位置的数(我们记录了以 (i) 开头,有 (j) 位的lunlun数有多少个)。

    然后后面的位置的数只有最多三种选择——上次减一,上次同样和上次加一(记住不能小于 (0) 或大于 (9))。

    然后再用相同的方法即可。

    #include <iostream>
    #include <algorithm>
    #include <map>
    #include <cmath>
    using namespace std;
    typedef long long ll;
    ll dp[10][20];//dp[i][j]代表以i开头的j位数有多少个lunlun 
    ll sum[20], pos;
    ll k;
    void dfs(ll num, ll lst) {
        if (num > pos) return;
        if (num == 1) {
            for (ll i = 1; i < 10; i++) {
                if (k > dp[i][pos - num + 1]) {
                    k -= dp[i][pos - num + 1];
                } else {
                    cout << i;
                    dfs(num + 1, i);
                    break;
                }
            }
        } else {
            for (ll i = lst - 1; i <= lst + 1; i++) {
                if (i < 0 || i > 9) continue;//记住特判 
                if (k > dp[i][pos - num + 1]) {
                    k -= dp[i][pos - num + 1];
                } else {
                    cout << i;
                    dfs(num + 1, i);
                    break;
                }
            }
        }
    }
    int main() {
        cin >> k;
        for (ll i = 0; i < 10; i++) {
            dp[i][1] = 1;
        }
        sum[1] = 9;
        for (ll j = 2; j <= 10; j++) {
            for (ll i = 0; i < 10; i++) {
                if (i != 0 && i != 9) dp[i][j] = dp[i - 1][j - 1] + dp[i][j - 1] + dp[i + 1][j - 1];
                else if (i != 0) dp[i][j] = dp[i - 1][j - 1] + dp[i][j - 1];
                else if (i != 9) dp[i][j] = dp[i][j - 1] + dp[i + 1][j - 1];
                if (i != 0) sum[j] += dp[i][j];
            }
        }
        for (ll i = 1; i <= 20; i++) {
            if (k > sum[i]) {
                k -= sum[i];
            } else {
                pos = i;
                break;
            }
        }
        dfs(1, 0);
        return 0;
    }
    
  • 相关阅读:
    docker下overlay2占用空间过大,清理docker占用空间
    js为浏览器URL追加参数
    img转Blob对象
    《ECharts》伪立体柱状图
    js分秒格式转时分秒
    表单边框缺一角效果
    File对象转base64
    《VUE》可编辑div限制字数
    quill富文本编辑器自定义字体、文字大小(编辑器内含element上传组件)
    我在华为工作十年的感悟(文摘)
  • 原文地址:https://www.cnblogs.com/zcr-blog/p/14897350.html
Copyright © 2011-2022 走看看