示例 - 如果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 - >
{
diff的范围= 100 - > 1 + 1 + 1 + 10 + 1 + 1 + 1 + 1 + 1 + 1 = f(n)说;
diff的范围= 1000 - > F(N)+ F(N)+ F(N)+ 10 * F(N)+ F(N)+ F(N)+ F(N)+ F(N)+ F(N)+ F(N )= ff(n)说
diff的范围= 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循环中每个数字的方法。感谢。
编辑 - 我已经到处搜索,但无法在任何地方找到它,所以,这不是重复。
答案 0 :(得分:2)
这是一种思考它的方法,可以指向你至少一个方向(或者,一个野鹅追逐)。分开这两个问题并删除重叠结果:
(1)j-digit
可以整除多少k
个数字? [j 9's / k] - [(j-1) 9's / k]
(2)有多少j-digit
个数字包含数字k
? 9 * 10^(k-1) - 8 x 9^(k-1)
现在我们需要减去j-digit
这两个可被k
整除的数字,并包含数字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的组合问题并得到了一些有趣的answers。这里有关于math.stackexchange的OP问题的链接:https://math.stackexchange.com/questions/1884303/the-n-th-number-that-contains-the-digit-k-or-is-divisible-by-k-2-le-k-l)
答案 1 :(得分:0)
跟进גלעד ברקן's answer,如果你有O(1)方式计算d(j, k)
=至少有一个数字k到j的数字,丢弃可被k整除的数字,那么您可以计算e(j, k)
=数字至少在数字k上,或者可以在j下将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=5
和k=2
之外,它们并不容易实现。
我强烈怀疑你可以针对这个问题改进O(log n);对于k
的某些值,它甚至可能无法访问。
答案 2 :(得分:0)
这比我想象的要复杂得多,但我想我找到了最简单情况的解决方案(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
也未显示,或者答案会变得太长。
答案 3 :(得分:-1)
这可以使用二进制搜索+数字dp解决。
时间复杂度为o(logn *)
解决方案,请参见代码:enter code here
https://ideone.com/poxhzd