如果数字按升序排列,则数字为“升序”。示例:1223469。“降序”数字的数字按降序排列。示例:9844300。不是“升序”或“降序”的数字称为“跳跃”。从1到100的数字不是“跳跃”。从101到10 ^ 60有多少“跳跃”数字?
答案 0 :(得分:3)
这是一个想法:不是计算跳跃数,而是计算升序和降序数。然后从所有数字中减去它们。
计算上升/下降应该很容易 - 你可以根据剩下的数字生成动态编程,以及你放在最后位置的数字。
答案 1 :(得分:3)
我将描述如何计算递增数字,因为这样更容易。从那里开始,你也可以计算下降的数量,然后从总数量中减去合计数量,补偿重复,如Ivan所示,或者设计一种更复杂的方式来直接计算跳数。
考虑按结束数字排序的数字。我们从1位数的数字开始,这将是我们的列表
1 // Amount of numbers ending with 1
1 // Amount of numbers ending with 2
1 // Amount of numbers ending with 3
1 // Amount of numbers ending with 4
1 // Amount of numbers ending with 5
1 // Amount of numbers ending with 6
1 // Amount of numbers ending with 7
1 // Amount of numbers ending with 8
1 // Amount of numbers ending with 9
要构建两位数以6结尾的数字,我们可以使用所有以6或更少结尾的数字
1 // Amount of numbers ending with 1 with 2 digits
2 // Amount of numbers ending with 2 with 2 digits
3 // Amount of numbers ending with 3 with 2 digits
4 // Amount of numbers ending with 4 with 2 digits
5 // Amount of numbers ending with 5 with 2 digits
6 // Amount of numbers ending with 6 with 2 digits
7 // Amount of numbers ending with 7 with 2 digits
8 // Amount of numbers ending with 8 with 2 digits
9 // Amount of numbers ending with 9 with 2 digits
并排编写这些内容,可以看到如何快速计算新值:
y a // y,a和x之前已经计算过了 x(a + x)
1 1 1 1
1 2 3 4
1 3 6 10
1 4 10 20
1 5 15 35
1 6 21 56
1 7 28 84
1 8 36 120
1 9 45 165
迭代一个这样的列,如果我们总是记住最后一次计算,我们可以直接生成新列的所有值。 scan()
函数完全抽象出取一个元素的行为,并用它和最后的结果做一些计算。
def scan(f, state, it):
for x in it:
state = f(state, x)
yield state
现在,生成下一列就像:
一样简单new_column = list(scan(operator.add, 0, column))
为简单起见,我们使用单个数字作为起点:
first_row = [1]*9
看到我们总是需要将新行反馈给该函数,可以再次使用scan来做到这一点:
def next_row(row):
return list(scan(operator.add, 0, column))
def next_row_wrapper(row, _):
return next_row(row)
>>> [list(x) for x in scan(next_row_wrapper, [1]*9, range(3))] # 3 iterations
[[1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 3, 6, 10, 15, 21, 28, 36, 45], [1, 4, 10, 20, 35, 56, 84, 120, 165]]
正如您所看到的,这使得前三行与第一行不同。
由于我们想知道所有数字的总和,我们可以做到这一点。当我们进行1次迭代时,我们得到所有递增的数字直到10 ^ 2,所以我们需要对所有数字进行59次迭代,直到10 ^ 60:
>>> sum(sum(x) for x in scan(lambda x, _: next_row(x), [1]*9, range(59))) + 10
56672074888L
对于降序数字,它非常相似:
>>> sum(sum(x) for x in scan(lambda x, _: next_row(x), [1]*10, range(59))) + 10 - 58
396704524157L<
想想数字如何结束:
从10到99,我们每个数字有两位数。
有
所有这些数字都作为100到999之间数字的前缀。
例如,有三个数字以3
结尾:
对于这三个数字中的每一个,我们可以创建七个递增数字:
很容易看出,这为七个可能的结束数字中的每一个添加了三个数字。
如果我们想要扩展以4结尾的数字,那么过程将类似:目前,有4个数字以4
结尾。因此,对于每个这样的数字,我们可以创建6个新的递增数字。这意味着,对于所有六个可能的结束数字,将会有额外的4个。
如果你已经理解了我在这里写的所有内容,那么应该很容易概括并实现一种算法来计算所有这些数字。
答案 2 :(得分:1)
非跳数:
69 choose 9
(升序数量≤60)+ 70 choose 10 - 60
(降序数量≤60)- 60 * 9
(重复计算:所有数字相同)- 1
(重复计数:零)=
453376598563 (要获得跳跃数字,从总数中减去:10 60 )
计算数字的简单python程序:
# I know Python doesn't do tail call elimination, but it's a good habit.
def choose(n, k, num=1, denom=1):
return num/denom if k == 0 else choose(n-1, k-1, num*n, denom*k)
def f(digits, base=10):
return choose(digits+base-1, base-1) + choose(digits+base, base) - digits*base - 1
升序数字:从0
开始,选择9个位置来递增数字。
降序数字:假装我们有一个数字10
,用于左边填充数字。然后选择10个位置来减少数字,从10
开始。然后删除10个选定位置连续而不是最后的所有选项,这将对应于前导0的数字序列。
由于所有数字都相同的数字都将由降序和递增算法产生,我们必须减去它们。
请注意,所有这些算法都认为数字0写入时根本没有数字。此外,所有数字≤100都是升序或降序(或两者),因此无需担心它们。
答案 3 :(得分:0)
您是将321计为下降还是将000000321视为跳跃?
提示答案:59位数的升序号码(69选10),因为你必须选择数字中哪些点位于不同的数字之间。