1811 E Living Sequence 两种解法

yizhihongxing

思维 进制转换 数位DP 无前导0 T3
Problem - 1811E - Codeforces

题目大意

从一个不含有数字4的递增序列中找第k个数并输出。
\(1,2,3,5,6,7,8,9,10,11,12\), \(k = 4\) 时输出 \(5\)

思路1

有一个巧妙的解法:
考虑这个问题, 从一个没有限制的从1开始的递增序列找出第k个数, 显然就是十进制的k。而这里则可以定义新的进制为 "012356789" 9进制, 那么k对应的就是这个特殊的九进制数, 我们只需要把它转换为十进制就行。

二转十:

while(k)
	ans += k % 2, k /= 2;

九转十:

while(k)
	ans += k % 9, k /= 9;

代码1

#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
using LL = long long;
int a[20];
int cnt = 0;

int main()
{

    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(0);
    string s = "012356789";
    int T;
    cin >> T;
    while (T--)
    {

        LL k;
        cin >> k;
        cnt = 0;
        while (k)
            a[cnt++] = s[k % 9] - '0', k /= 9;
        for (int i = cnt - 1; i >= 0; i--)
            cout << a[i];
        cout << endl;
    }
}

思路2

也可以考虑数位DP, 定义 \(f(i,j)\) 为长度为i, 且最高位为j的数, 可以写出这样的初始化函数来得到 \([1,i]\) 的满足条件的数的个数:

void init()
{
    for (int i = 0; i <= 9; i++)
        if (i != 4)
            f[1][i] = 1;
    for (int i = 2; i <= N - 1; i++)
    {
        for (int j = 0; j <= 9; j++)
        {
            if (j == 4)
                continue;
            for (int k = 0; k <= 9; k++)
                f[i][j] += f[i - 1][k];
        }
    }
}

然后再实现查找前缀和 \([1,num]\) 的满足条件的数的个数, 题目中的 \(k\) 最大为 1e12, 直接二分结果, 找最左边且 \(dp(mid) = k\) 的值就是最终结果。

记得要处理前导0, 方法是在首尾不加上0开头的部分, 最后再加一遍所有长度小于 num.size() 的部分。

代码2

#include <iostream>
#include <cstring>
#include <algorithm>
#include <string>
#include <cmath>
#include <vector>
using namespace std;
const int N = 17;
typedef long long ll;
const ll INF = 1e17;
ll f[N][10];

void init()
{
    for (int i = 0; i <= 9; i++)
        if (i != 4)
            f[1][i] = 1;
    for (int i = 2; i <= N - 1; i++)
    {
        for (int j = 0; j <= 9; j++)
        {
            if (j == 4)
                continue;
            for (int k = 0; k <= 9; k++)
                f[i][j] += f[i - 1][k];
        }
    }
}

ll dp(ll x)
{
    if (!x)
        return 0;

    vector<int> nums;
    while (x)
        nums.push_back(x % 10), x /= 10;

    ll res = 0;
    for (int i = nums.size() - 1; i >= 0; i--)
    {
        int x = nums[i];
        for (int j = (i == nums.size() - 1); j < x; j++)
            res += f[i + 1][j];
        if (x == 4)
            break;
        if (!i)
            res++;
    }
    for (int i = 1; i <= nums.size() - 1; i++)
        for (int j = 1; j <= 9; j++)
            res += f[i][j];
    return res;
}

int main()
{
    init();

    int T;
    cin >> T;
    while (T--)
    {
        ll k;
        cin >> k;
        ll l = -1, r = 1e13;
        while (l != r - 1)
        {
            ll mid = l + r >> 1;
            if (dp(mid) < k)
                l = mid;
            else
                r = mid;
        }
        cout << r << endl;
    }
    return 0;
}

原文链接:https://www.cnblogs.com/edwinaze/p/17316429.html

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:1811 E Living Sequence 两种解法 - Python技术站

(0)
上一篇 2023年4月17日
下一篇 2023年4月17日

相关文章

  • Java数据结构最清晰图解二叉树前 中 后序遍历

    Java数据结构最清晰图解二叉树前 中 后序遍历 前言 二叉树是数据结构中至关重要的一种数据结构,对于计算机科学的学习和工作都是至关重要的。而遍历二叉树是二叉树的重要操作之一。 为了帮助读者更好地理解二叉树前、中、后序遍历的过程,本文介绍 Java 数据结构中最清晰的图解二叉树前、中、后序遍历攻略。 什么是二叉树? 二叉树是一种非常重要的数据结构,它由根节点…

    数据结构 2023年5月17日
    00
  • python查找与排序算法详解(示图+代码)

    下面是关于“Python查找与排序算法详解”的完整攻略。 1. 查找算法 1.1 线性查找算法 线性查找算法是一种简单的查找算法,它的基本思想是从数据集合的第一个元素开始逐个比较,直到找到目标元素或遍完整个数据集合。在Python中,我们可以使用线性查找算法来查找任意数据类型的元素。 下面使用Python实现性查算法: def linear_search(a…

    python 2023年5月13日
    00
  • TypeScript 基础数据结构哈希表 HashTable教程

    TypeScript 基础数据结构哈希表 HashTable 教程 什么是哈希表 HashTable 在计算机科学中,哈希表(HashTable),也叫散列表,是根据关键码值(Key­value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫作哈希函数,存放记录的数组叫作哈希表。 如何实现哈…

    数据结构 2023年5月17日
    00
  • C语言 数据结构中栈的实现代码

    下面是关于C语言中栈的实现代码的详细攻略: 栈的概念 栈是一种只能在一端进行插入或删除操作的线性数据结构,它具有后进先出(Last In First Out, LIFO)的特点。通俗的说,就像大家在平时搭积木那样,搭积木的时候总是从最下面开始往上搭,拿积木的时候总是从最上面的积木开始拿起,栈就是这么一个先进后出的数据结构。 栈的实现方法 栈的实现方法比较多,…

    数据结构 2023年5月17日
    00
  • Lua教程(七):数据结构详解

    Lua教程(七):数据结构详解 Lua 中的数据结构广泛应用于各种计算机程序中。本文将详细介绍 Lua 中的数组、列表、栈、队列、集合和字典等数据结构的使用以及相关的函数。 数组 数组是存储在连续内存位置上的相同数据类型的元素集合。Lua 中的数组索引默认从 1 开始。下面是一些常用的 Lua 数组函数: table.concat(arr[, sep[, i…

    数据结构 2023年5月17日
    00
  • Java数据结构之栈与队列实例详解

    Java数据结构之栈与队列实例详解攻略 简介 栈和队列是常见的数据结构,在Java中也有对应的实现方式。本文将介绍栈和队列的概念、常见实现方式、应用场景和两个示例。 栈 概念 栈是一种具有后进先出(Last In First Out)特性的数据结构。栈可以使用数组或链表实现。 常见实现方式 基于数组的栈实现 使用数组作为底层存储结构实现栈时,需要注意栈顶指针…

    数据结构 2023年5月17日
    00
  • Python实现搜索算法的实例代码

    Python实现搜索算法的完整攻略 搜索算法是计算机科学中的基本算法之一,它的主要目的是在一组数据中查找特定的元素。在Python中,可以使用简单的代码实现常用的搜索算法。本文将详细讲解Python实现搜索算法的过程,并提供两个示例说明。 线性搜索 线性搜索是一种简单的搜索算法,它的基本思想是从一组数据的第一个元素开始,依次比较每个元素,直到找到目标元素或搜…

    python 2023年5月13日
    00
  • 基于Python实现Hash算法

    下面是关于“基于Python实现Hash算法”的完整攻略。 1. Hash算法简介 Hash算法是一种将任意长度消息压缩到某一固定长度的算法。Hash算法的主要应用包括数据加密、数字签名、数据完整性校验等。常见的Hash算包括MD5、SHA-1、SHA-256等。 2. Python实现Hash算法 在Python中,我们可以使用 hash 模块来实现Has…

    python 2023年5月13日
    00
合作推广
合作推广
分享本页
返回顶部