Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 我必须找到第n个数字,它包含数字k或者可以被k整除。(2<;=k<;=9)_Algorithm_Math_Sequence - Fatal编程技术网

Algorithm 我必须找到第n个数字,它包含数字k或者可以被k整除。(2<;=k<;=9)

Algorithm 我必须找到第n个数字,它包含数字k或者可以被k整除。(2<;=k<;=9),algorithm,math,sequence,Algorithm,Math,Sequence,示例–如果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+4+3+3+4+3+3+4的倍数 用于包含数字3-> { 范围在diff=100->1+1+1+10+1+1+1+1+1+1=f(n)说 差异范围=1000-> f(n)+f(n)+f(n)+10*f(n)+f(n)+f(n)+f(n)+f(n)+f(n)+f(n)+f(n)=ff(n)说 差异范围

示例–如果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+4+3+3+4+3+3+4的倍数

用于包含数字3->

{

范围在diff=100->1+1+1+10+1+1+1+1+1+1=f(n)说

差异范围=1000-> f(n)+f(n)+f(n)+10*f(n)+f(n)+f(n)+f(n)+f(n)+f(n)+f(n)+f(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)+ff(n)+ff(n)+ff(n)

这一点更进一步

}

我必须用比O(n)或O(1)更好的答案,如果可能的话,请不要建议像检查for循环中的每个数字这样的方法。谢谢


编辑-我到处都搜索过,但在任何地方都找不到答案,因此,它不是重复的。

这里有一种方法可以让你思考它,它至少可以指向一个方向(或者,一个白鹅追逐)。将两个问题分开并删除重叠的结果:

(1) 有多少个j位数可以被k整除<代码>[j 9/k]-[(j-1)9/k]

(2) 有多少个
j位
数字包括数字
k
<代码>9*10^(k-1)-8 x 9^(k-1)

现在我们需要减去既可被
k
整除的
j位
数字,并包括数字
k
。但是有多少呢

使用可分性规则来考虑不同的情况。例如:

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的组合问题,得到了一些有趣的答案。这里有一个指向OP关于math.stackexchange的问题的链接:)

接下来,如果你有一个O(1)方法来计算
d(j,k)
=至少有一位k到j的数字,丢弃可被k整除的数字,然后您可以计算
e(j,k)
=至少在数字k上或在j下可被k整除的数字,如
j/k+d(j,k)


这允许您使用二进制搜索查找
f(n,k)
,因为
k这比我想象的要复杂,但我想我找到了最简单情况(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,依此类推。困难的部分是计算系数(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个值都在序列中:[201300],因此如果110 n) 打破 nn+=tmp; s+=10^ii*2; } } } 返回s;

这是唯一未经测试的未完成伪代码(我知道您不能在Java中使用
^
),ii=1或0需要作为特例处理,此缺失以及如何查找
I
也没有显示,否则答案将变得太长

这可以使用二进制搜索+数字dp解决。。。。。 时间复杂度为o(logn*)
有关解决方案,请参见代码:
在此处输入代码

我可以想象O(logn),但对于O(1),您基本上需要找到一个公式f(n,k)=解决方案或不解决方案?建议我O(logn)。。谢谢。@maraca肯定对解决这个问题非常感兴趣,不仅仅是简单的循环。不管怎么说,数字的数量都必须是log_10(n),因为每10个数字中至少有1个是k,但如果小于log_10(n)-1个数字,你根本就没有n个数字。事实上,它是ceil(log_10(n))或ceil(log_10(n))+1。现在去读吉拉德的答案:)这个答案看起来不错。为了计算出重叠的结果,可以使用基于DP[x][y]=包含特殊数字的x位数(其值等于特殊数字的y模)以及DP2[x][y]的动态规划=不包含值等于y mod special digit的特殊数字的x位数。@PeterDrivaz感谢您的评论。我必须考虑一下你建议的DB定义,看看我是否理解。你们能提供一个有效的实现吗?我看不出一种方法可以轻易地得到第n个数字。谢谢。@rishavbansal一种方法可能是:一旦你确定了第n个
n
数字的位数,修复最左边的数字,然后向右移动——比如,如果最左边的数字是
1
,使用组合学和可分性规则计算了多少特殊数字?如果是
2
?等等。当你找到合适的最左边的数字时,转到它右边的下一个数字,依此类推。@rishavbansal这里也看到了,为什么3和9的组合/整除选项不是很重要呢?我不知道如何使用7:)那么,有多少数字6可以被3整除,比如说5000?一件事是存在一个整除性规则(也有一个用于7),另一件事是使用该规则在不循环j次的情况下得到d(j,k)。给你:2,18,162,1458…=2*(9^0,9^1,9^2,9^3…)良好的观察+1。现在我把答案保持原样,因为它显示了我是如何得出这些数字的,也许它可以以某种方式推广到任何k。我已经从这个链接上我的问题的答案中推导出了一个解决方案,似乎效果很好。
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;