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日

相关文章

  • 带你了解Java数据结构和算法之2-3-4树

    带你了解Java数据结构和算法之2-3-4树 1. 什么是2-3-4树 2-3-4树是一种自平衡二叉查找树,也叫B树的一种,它可以保持树的平衡,使得每个节点的左右子树高度差最多为1。在2-3-4树中,每个节点可以包含2个、3个或4个子节点,这也是其名称的来源。2-3-4树是B树的特殊形式,通常用于内存储存结构。 2. 2-3-4树的特点 2-3-4树的特点如…

    数据结构 2023年5月17日
    00
  • C++高级数据结构之二叉查找树

    C++高级数据结构之二叉查找树 什么是二叉查找树 二叉查找树,也称二叉搜索树(BST,Binary Search Tree),是一种常见的基于二叉树的数据结构,主要用于快速查找与排序。在二叉查找树上,左子树的每个节点都比其根节点小,右子树的每个节点都比其根节点大,同时整棵树也满足二叉树的性质。 二叉查找树的实现 我们可以通过C++语言实现二叉查找树的基本操作…

    数据结构 2023年5月17日
    00
  • 一文学会数据结构-堆

    一文学会数据结构-堆 什么是堆 在计算机科学中,堆是一个特殊的树状数据结构。堆通常有如下几个特性: 堆是完全二叉树; 堆中每个节点的值都大于或等于(小于或等于)其子节点的值,这个取值规则称为堆的“属性”; 堆顶元素(即根节点)总是为最大值或最小值。 堆的种类 堆分为小根堆和大根堆两种。小根堆要求每个节点的值都不大于其父节点的值,即A[PARENT[i]] &…

    数据结构 2023年5月17日
    00
  • 详解Python中4种超参自动优化算法的实现

    下面是关于“详解Python中4种超参自动优化算法的实现”的完整攻略。 1. 超参自动化算法简介 超参自动优化算法是种自动化调参的方法,它可以自动地搜索超参数空,找到优的超参数组合,从而提高模型的性能。Python中常用的超参自动优化算法包括网格搜索、随机搜索、贝叶优化和遗传算法。 2. Python实现超参自动优化算法 2.1 网格搜索 网格搜索是一种简单…

    python 2023年5月13日
    00
  • python3实现常见的排序算法(示例代码)

    Python3实现常见的排序算法 排序算法是计算机科学中的基本算法之一,它可以将一组无序的数据按照一定的规则进行排序。在Python3中,可以使用多种算法来实现排序,包括冒泡排序、选择排序、插入排序、快速排序、归并排序等。本文将详细讲解Python3实现常见的排序算法的完整攻略,包括算法原理、Python3实现过程和示例。 冒泡排序 冒泡排序是一种简单的排序…

    python 2023年5月13日
    00
  • Python实现最短路径问题的方法

    最短路径问题是计算机科学中的一个经典问题,它的目标是在一个加权图中找到两个节点之间的最短路径。在Python中,我们可以使用Dijkstra算法和Bellman-Ford算法来解决最短路径问题。 Dijkstra算法 Dijkstra算法是一种贪心算法,它的基本思想是从起点,每次选择距离起点最近的节点,并更新与该节点相邻的节点的距离。在Python中,我们可…

    python 2023年5月14日
    00
  • Python矩阵常见运算操作实例总结

    下面是详细讲解“Python矩阵常见运算操作实例总结”的完整攻略。 1. 什么是矩阵 矩阵是一个由数值排成的矩形阵列,其中每个数值称为阵的元素。矩阵在数学、物理、工程等领域中有广泛的应用,例如线性代数、图像处理、机器学习等。 2. Python中的矩阵运算 Python中有多种库可以用于矩阵运算,例如NumPy、SciPy、Pandas等。以下是一些常见的矩…

    python 2023年5月14日
    00
  • Python实现随机爬山算法

    Python实现随机爬山算法 随机爬山算法是一种常用的优化算法,它的主要思想是从一个随机的起点开始,每次随机选择一个相邻的状态,并根据目标函数的值决定是否接受该状态。本文将详细讲解如何使用Python实现随机爬山算法,并提供两个示例说明。 随机爬山算法原理 随机爬山算法的基本思想是从一个随机的起点开始,每次随机选择一个相邻的状态,并根据目标函数的值决定是否受…

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