用于计算不包含给定数字的第n个数字的程序

Program to compute n-th number that doesn't contain given digit

本文关键字:数字 程序 计算 包含 用于      更新时间:2023-10-16

我被要求编写一个C 程序,该程序计算 n-th 数字,不包含一个给定的数字时间执行时间低于0.1秒。内存似乎不是一个问题,因为我允许最多使用64 MB。

问题的原始文本如下:

cifra4

represent numbers,决定不使用Digit C 再次。 因此,从一系列自然数中,所有包含的数字 数字C将被删除。让新数组为 S

要求

1)确定 s 中的N-th号。

2) YZ是两个天然 来自所有自然数字的数字。确定
的数量 从YZ删除的自然数。

输入数据

输入文件cifra4.in包含第一个数字T代表 要求类型。如果T == 1,第二行将包含 数字C和数字N。如果T == 2, 第二行将包含Digit C和两个自然数Y,并且 Z

输出数据

在输出文件中cifra4.out中将包含在第一行中 根据要求的类型。

限制和澄清

1 ≤ N ≤ 10 ^ 13
0 ≤ C ≤ 9
1 ≤ Y ≤ 10 ^ 13
1 ≤ Z ≤ 10 ^ 13
for 20% of the tests, N will have a maximum of 5 digits
for 20% of the tests, Y and Z will have a maximum of 6 digits

示例1

cifra4.in

1
0 11

cifra4.out

12

示例2

cifra4.in

2
1 3 20

cifra4.out

10

我最好的尝试是一个确定(或至少应该)的代码,该n不包含数字" 0",但对于10 ^ 13,它返回了23210987654321,显然包含0

我的速度较慢,但是正确的方法是我最终保持的。这是代码:

#include <fstream>
std::ifstream in("cifra4.in");
std::ofstream out("cifra4.out");
const long long pow_of_10[14] = {0, 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000,
                                 10000000000, 100000000000, 1000000000000};
void req_1 ()
{
    short digit;
    long long n;
    in >> digit >> n;
    for (long long i = 0; i <= n; i++)
    {
        long long nr = i;
        if (nr)
        {
            long k = 1;
            do
            {
                if (nr % 10 == digit)
                {
                    n += pow_of_10[k];
                    i += pow_of_10[k] - 1;
                    break;
                }
                nr /= 10;
                k++;
            }
            while (nr);
        }
        else if (digit == 0) n++;
    }
    out << n - 1;
}
void req_2()
{
    short digit;
    long long lhs, rhs;
    long long elim = 0;
    in >> digit >> lhs >> rhs;
    for (long long i = lhs; i <= rhs; i++)
    {
        long long nr = i;
        while (nr)
        {
            if (nr % 10 == digit)
            {
                elim++;
                break;
            }
            nr /= 10;
        }
    }
    out << elim;
}
int main()
{
    short requirement;
    in >> requirement;
    if (requirement == 1)
        req_1();
    else
        req_2();
}

注意

我不是要在必要的情况下要求代码,而是为了想法,可能在不错的时间内执行10 ^ 13的可能算法,最好是问题所要求的时间,但是1秒对我来说会很好。

想象9是禁止的数字。在这种情况下,您只需将您的号码转换为Base-9就完成了。

现在,d说,禁止数字不同时会发生什么?它仍然是一个基本9号,但您必须映射数字,以使d以下的数字保持不受影响,并且d及以上映射到Digit d + 1

例如,当禁止数字为 7时, n125

  • 步骤1:转换为9:125 10 = 148 9
  • 步骤2:映射数字。1→1,4→4,8→9

解决方案是149。

,由于一个数字的十进制数字是彼此"独立"的,因此,一个数字不会影响任何其他数字 - 一旦您修复了一个前缀(至少一个)数字更重要,留下n'不太重要的数字,您知道自己完全具有(10-1)^n'= 9^n'数字,该前缀和未连接部分中没有禁止数字。例如,对于以1开头的3位数字,它们中有81个数字,其中没有0。

这里唯一的"障碍"是将最重要的数字设置为零,这意味着您获得了不同数字数字(012、0012等)的相同数字。但是,您也应该能够解决这个问题 - 通过确定在没有禁止数字的情况下需要多少位数字的数字。与我上面描述的论点非常相似。然后,您知道如果您的禁止数字为0或10-2 = 8,则在那里有10-1 = 9个选项。