查找第n个包含数字k或可被k整除的数。(2 <= k <= 9)

4

例子 - 如果n = 15且k = 3,答案是:33(3, 6, 9, 12, 13, 15, 18, 21, 23, 24, 27, 30, 31, 32, 33)

我开始按顺序进行,但无法归纳出规律。

对于3的倍数 -> 3+3+3+4+3+3+4+3+3+4

对于包含数字3的数 ->

{

在差异范围为100的范围内 -> 1+1+1+10+1+1+1+1+1+1 = f(n),这里假设为f(n);

在差异范围为1000的范围内 -> f(n)+f(n)+f(n)+10*f(n)+f(n)+f(n)+f(n)+f(n)+f(n)+f(n) = ff(n),这里假设为ff(n)

在差异范围为10000的范围内 -> ff(n) + ff(n) + ff(n) + 10*ff(n)+ff(n) + ff(n) + ff(n)+ff(n) + ff(n) + ff(n)

同样的方法可以延伸下去。

请提供O(n)以上甚至O(1)的更好方法,不要建议使用for循环来检查每个数字。谢谢。

编辑 - 我已经在各处搜索,但无法找到答案,因此这不是重复问题。


5
我能想象O(logn),但对于O(1),你基本上需要找到一个公式f(n,k)=解或不解。 - maraca
建议我使用O(logn)。谢谢。 - user6464950
@maraca 绝对对解决这个问题非常感兴趣,超越了天真的循环。 - D. Ben Knoble
1
不管任何情况,数字的数量约为log_10(n),因为至少有十分之一的数字含有k作为数字,但是如果位数小于log_10(n)-1,则根本没有n个数字。事实上,它要么是ceil(log_10(n)),要么是ceil(log_10(n))+1。现在去读Gilad的答案 :) - einpoklum
4个回答

1
这里有一种思考方式,可以至少指出一个方向(或者说是一次野鸡追逐),将两个问题分开并消除重叠结果:
(1) 有多少个 j位数 能被 k 整除?[j个9 / k] - [(j-1)个9 / k]
(2) 有多少个 j位数 包含数字 k9 * 10^(k-1) - 8 x 9^(k-1)
现在我们需要减去既能被 k 整除,又包含数字 kj位数 数量。但是有多少个呢?
使用整除规则来考虑不同的情况。例如:
k = 2
If k is the rightmost digit, any combination of the previous j-1 digits would work.
Otherwise, only combinations with 0,4,6 or 8 as the rightmost digit would work.

k = 5
If k is the rightmost digit, any combination of the previous j-1 digits would work.
Otherwise, only combinations with 0 or 5 as the rightmost digit would work.

etc.

(附录:我在math.stackexchange上提出了组合问题,并得到了一些有趣的答案answers。这里是原帖在math.stackexchange上的链接:https://math.stackexchange.com/questions/1884303/the-n-th-number-that-contains-the-digit-k-or-is-divisible-by-k-2-le-k-l。)

这个答案看起来不错。为了计算重叠的结果,可以使用基于动态规划的方法,例如DP[x][y] = 包含特殊数字值等于模数y的x位数字的数量,以及可能的DP2[x][y] = 不包含特殊数字值等于模数y的特殊数字的x位数字的数量。 - Peter de Rivaz
你们能提供一个可行的实现吗?我没有找到一个简单获取第n个数字的方法。谢谢。 - user6464950
1
@rishavbansal 在这里也看一下,http://math.stackexchange.com/questions/1885253/how-many-k-digit-numbers-are-both-divisible-by-3-and-include-the-digit-3/1885287#1885287 - גלעד ברקן
@PeterdeRivaz请查看我答案末尾的math.stackexchange上OP问题的链接 - 看起来那里的建议与您的相似。 - גלעד ברקן
该死的math.stackexchange!我差点就做出来了 :-) - m69 ''snarky and unwelcoming''
显示剩余4条评论

-1

这个问题可以使用二分查找+数字动态规划来解决...... 时间复杂度为o(logn*) 有关解决方案,请参见代码:enter code herehttps://ideone.com/poxhzd


-1

关于גלעד ברקן的回答,如果您有一种O(1)的方法来计算d(j, k) = j以下至少有一个数字k的数字,丢弃可被k整除的数字,那么您可以将e(j, k) = j以下至少有一个数字k或可被k整除的数字计算为j/k + d(j, k)

这使您能够使用二分查找找到f(n, k),因为k <= f(n, k) <= k*n并且e(j, k) = n <=> f(n, k) = j:您实际上是尝试猜测哪个j会产生预期的n,在O(log n)次尝试中。

我同意גלעד ברקן的观察结果,即用于有效计算d(j, k)的可整除性规则;但是,它们不容易实现,除了k=5k=2之外。

我强烈怀疑你能够在这个问题上达到O(log n)的改进;对于某些值的 k,甚至可能无法实现。


为什么组合数/可被3和9整除的选项不是同样的简单呢?我对如何用7做这个问题感到困惑 :) - גלעד ברקן
那么,有多少个带数字 6 的数可以被 3 整除,在 5000 以下呢?一个问题是有可行的整除规则(7 也有一种),而另一个问题是使用该规则而不用循环 j 次来得到 d(j, k)。 - tucuxi
1
请看这里:http://math.stackexchange.com/questions/1885253/how-many-k-digit-numbers-are-both-divisible-by-3-and-include-the-digit-3/1885287#1885287 - גלעד ברקן

-1

这比我想象的要复杂,但我认为我已经想出了最简单情况(k=2)的解决方案。

首先,我尝试通过提出以下问题来简化:序列中哪个位置有数字10^i * k(其中i = 1, 2, 3, ...)?对于k = 2,这些数字是20、200、2000,...

i k                                                                  n
1 2    20/2                                                        = 10
2 2   200/2 + 2*  5                                                = 110
3 2  2000/2 + 2* 50        + 18* 5                                 = 1190
4 2 20000/2 + 2*500        + 18*50         + 162*5                 = 12710
i 2    10^i + 2*10^(i-1)/2 + 18*10^(i-2)/2 + 162*10^(i-3)/2 + ?*10^(i-4)/2 + ...

在最后一行,我试图表达这个模式。第一部分是可被2整除的数字。然后还有i-1个附加部分,用于首位为2、第二位以此类推的奇数。困难的部分是计算因子(2,18,162等)。
下面是一个函数,返回任何i所需的新因子:
f(i) = 2 * 10^(i-2) - sum(10^(i-x-1)*f(x), x from 2 to i-1) = 2 * 9^(i-2) [thx @m69]
f(2) = 2
f(3) = 2*10 - (1*2) = 18
f(4) = 2*100 - (10*2 + 1*18) = 162
f(5) = 2*1000 - (100*2 + 10*18 + 1*162) = 1458

因此,我们可以使用以下算法:

找到不超过位置的最高数字10^i*2。(如果n在范围[positionOf(10^i*2), positionOf(10^i*2) + (10^i)]内,则我们已经知道解决方案:10^i*2 + (n - positionOf(10^i*2))。例如,如果我们发现i=2,我们知道下一个100个值都在序列中:[201, 300],所以如果110 <= n <= 210,则解决方案为200+(n-110) = n+90。)

int nn = positionOf(10^i * 2);
int s = 10^i * 2;
for (int ii = i; ii >= 0; ii--) {
  for (int j = 1; j < 10; j++) {
    if (j == 1 || j == 6) {
      if (n <= nn + 10^ii)
        return s + nn - n;
      nn += 10^ii;
      s += 10^ii;
      int tmp = positionOf(10^ii);
      if (nn +  tmp > n)
        break;
      nn += tmp;
      s += 10^ii;
    } else {
      int tmp = positionOf(10^ii * 2);
      if (nn + tmp > n)
        break;
      nn += tmp;
      s += 10^ii * 2;
    }
  }
}
return s;

这只是未经测试的不完整的伪代码(我知道在Java中不能使用^),ii = 1或0需要被视为特殊情况,这个缺失以及如何找到i也没有显示,否则答案会变得太长。


1
2、18、162、1458... = 2 * (9^0、9^1、9^2、9^3...) - m69 ''snarky and unwelcoming''
好的观察 +1。目前我将答案保留原样,因为它展示了我如何得出这些数字,也许可以以某种方式推广到任何k。 - maraca
我从这个链接上我的问题的答案中推导出了一个解决方案,似乎运行良好。 - user6464950

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接