有两行数字,第1行是从0开始的连续数字,现在请您填写第2行,以确保第2行的数字是第1行的对应数字出现在第2行的次数。
例如:
0 1 2 3 4 5 6 7 8 9
_ _ _ _ _ _ _ _ _ _
更具体地说,我们使用row1
第 1 行和row2
第 2 行,我们填写row2
以确保它满足:row2[i] = count(row2, row1[i])
。表示其中count(row2, row1[i])
的频率计数。row1[i]
row2
有两行数字,第1行是从0开始的连续数字,现在请您填写第2行,以确保第2行的数字是第1行的对应数字出现在第2行的次数。
例如:
0 1 2 3 4 5 6 7 8 9
_ _ _ _ _ _ _ _ _ _
更具体地说,我们使用row1
第 1 行和row2
第 2 行,我们填写row2
以确保它满足:row2[i] = count(row2, row1[i])
。表示其中count(row2, row1[i])
的频率计数。row1[i]
row2
在 1000 次运行中,此解决方案必须平均运行循环 3.608 次
import random
def f(x):
l = []
for i in range(10):
l.append(x.count(i))
return l
fast = list(range(10))
while f(fast) != fast:
fast = []
slow = []
for i in range(10):
r = random.randint(0,9)
fast.append(r)
slow.append(r)
while True:
fast = f(f(fast))
slow = f(slow)
if fast == slow:
break
print(fast)
f(x) 进行猜测 x 并返回计数。我们本质上是在寻找一个满足 f(x) = x 的解决方案。
我们首先从 0-9 中选择 10 个随机整数并列一个列表。我们的目标是重复将此列表设置为等于自身,直到我们找到解决方案或陷入循环。为了检查循环,我们使用 Tortoise 和 Hair 算法,它们以 2 种速度移动。快的速度是慢速度的两倍。如果它们相等,我们就会进入一个循环并从一个新的随机场景开始。
我跑了几次,找到了 n>6 的一般解决方案(在这种情况下 n = 10)。它的形式为 [n-4,2,1,0...,0,1,0,0,0]
我们可以用数学方法解决这个问题。
让我们称我们的解决方案s
和p
的子集s
,其中s[i] > 0
,即表示数字的集合(任何零都是未表示的数字或索引)。
我们可以这么说n = sum of all frequencies = sum p
现在让我们调用withoutp'
的子集,它们只是大于零的数字的频率。p
s[0]
显然sum p' = sum p - s[0] = length p
,这只是计算有多少数字s
大于零。
记住这一点length p = length p' + 1
。现在如果length p > 4
,我们知道了,sum p' > 4
剩下的m
长度分区 ( p'
) 必须总和为m+1
,其中m > 3
。可以做到这一点的唯一方法是使用(m-1)
1 和一个 2,例如,[1,1,1,2]
在m=4
(根据定义,在 中没有零p'
)的情况下。这样的分区作为我们问题的解决方案是没有意义的,因此我们看到p
,或者我们的解决方案中大于零的数字子集,必须少于 5 个元素。
现在我们可以解决特定情况:
每个解决方案都必须有s[0] > 0
,因为零列中的零将使解决方案无效。
length p = 1
s[0]
只有在同时为零和大于零的情况下才有可能。
length p = 2
暗示p' = [2]
,所以有两个零和两个 2,s=[2,0,2,0]
length p = 3
暗示p' = [1,2]
。因为我们知道只有一个s[i]
,即s[0] > 0
2 inp'
必须要么引用它自己,在这种情况下我们有s=[2,1,2,0,0]
; 或两个 1,因此s=[1,2,1,0]
length p = 4, p' = [2,1,1]
. 在这种情况下,2 只能指两个 1,我们必须假设s[0] > 2
,这也意味着sum p >= (3+2+1+1 = 7)
。这是 user1125600 发现的最终/一般情况:s[1]=2, s[2]=1
。最后一个 1 指代s[0]
,因此它的索引等于s[0]
。记住sum p - s[0] = length p
,我们得到 ,s[0] = n - 4
和解,对于 p = 4,n > 6:s=[n - 4,2,1...1,0,0,0]
解决方法:蛮力。10 的整数分区只有 42个。尝试所有这些,看看哪一个有效。