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;
    }
    
  • 相关阅读:
    739. Daily Temperatures
    556. Next Greater Element III
    1078. Occurrences After Bigram
    1053. Previous Permutation With One Swap
    565. Array Nesting
    1052. Grumpy Bookstore Owner
    1051. Height Checker
    数据库入门及SQL基本语法
    ISCSI的概念
    配置一个IP SAN 存储服务器
  • 原文地址:https://www.cnblogs.com/zcr-blog/p/14897350.html
Copyright © 2011-2022 走看看