1811 E Living Sequence 两种解法

思维 进制转换 数位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日

相关文章

  • C++高级数据结构之并查集

    C++高级数据结构之并查集 什么是并查集 并查集(Union Find Set)是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。常常在使用中以森林来表示。 并查集定义了如下的三种操作: 1、makeSet(s):建立一个新的并查集,其中包含s个单元素集合。 2、unionSet(x, y):把元素x和元素y所在的集…

    数据结构 2023年5月17日
    00
  • SVM算法的理解及其Python实现多分类和二分类问题

    下面是SVM算法的理解及其Python实现多分类和二分类问题的完整攻略,包含两个示例说明。 算法 支持向量机(SVM)是一种常用的监督学习算法,用于分类和回归分析。SVM的基本思想是将数据映射到高维空间中,使得数据在该空间中线性可分。然后,SVM找到一个最优的超平面,将数据分为不同的类别。SVM的优点是可以处理高维数据,具有较高的准确性和鲁棒性。 SVM算法…

    python 2023年5月14日
    00
  • C语言数据结构之迷宫问题

    C语言数据结构之迷宫问题 迷宫问题是一种基本的搜索问题,其中需要在一个矩阵中寻找从起点到终点的路径。在本篇文章中,我们将以C语言为例,介绍迷宫问题的完整攻略。 准备工作 在开始之前,我们先要准备好数据结构。为了表示迷宫,我们使用一个二维数组。其中,0表示可以通过的路,1表示障碍物不可通过。为了记录路径,我们还需要使用一个二维数组来表示每个格子是否已经被访问过…

    数据结构 2023年5月17日
    00
  • Java数据结构与算法学习之循环链表

    Java数据结构与算法学习之循环链表 本文将详细介绍Java数据结构中的一种链表类型——循环链表,并讲解如何使用Java实现循环链表。同时,本文也提供了两个示例,方便读者更好地理解和运用循环链表。 什么是循环链表 循环链表是一种链表,它与单向链表和双向链表不同之处在于它的最后一个结点指向第一个结点。这就形成了一个循环链,因此称之为循环链表。 如何实现循环链表…

    数据结构 2023年5月17日
    00
  • Python数据结构树与算法分析

    Python数据结构树与算法分析 树是一种非常重要的数据结构,它在计算机科学中有着广泛的应用。在Python中,使用多种来实现树,包括列表、字典、类等。本文将详细讲解Python数据结构树与算法分析的完整攻略包括树的基本概念、Python实现过程和示例。 树的基本概念 树是一种非线性的数据结构它由一组节点和一组边组成。树的基本概念包括: 根节点:树的顶部节点…

    python 2023年5月13日
    00
  • Python实现的朴素贝叶斯算法经典示例【测试可用】

    Python实现的朴素贝叶斯算法经典示例【测试可用】详细攻略 朴素贝叶斯算法是一种常见分类算法,它基于贝叶斯定理和特征条件独立假设,可以用于文本分类、圾邮件过滤、情感分析等领域。在本文中,我们将介绍Python实现的朴素贝叶斯算法经典示例,并提供测试代码。 朴素贝叶斯算法原理 朴素贝叶斯算法是一种基于贝叶斯定理的分类算法,它假设每个特征之间是相互独立的,即特…

    python 2023年5月14日
    00
  • C#数据结构之堆栈(Stack)实例详解

    C#数据结构之堆栈(Stack)实例详解 在编程中,我们经常需要保存一些数据,这些数据可以根据其进入的先后顺序以及其他规则进行处理和访问。其中,堆栈(Stack)是一种简单但是非常有用的数据结构。本文将为大家详细讲解堆栈(Stack)的概念、用法以及C#中的实现方法。 堆栈(Stack)概述 堆栈(Stack)是一种后进先出(LIFO)的数据结构。也就是说,…

    数据结构 2023年5月17日
    00
  • C语言数据结构图的创建与遍历实验示例

    下面是“C语言数据结构图的创建与遍历实验示例”的完整攻略。 1. 创建数据结构图 1.1 创建图对象 首先需要创建一个图对象,可以使用邻接矩阵或邻接表来表示图。使用邻接矩阵表示时,将所有顶点的编号按照一定顺序排列在矩阵的行和列上,使用0或1表示两个顶点之间是否有边。使用邻接表表示时,需要一个array存储所有的顶点,数组中的每个元素包含一个链表,链表中存储与…

    数据结构 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部