Algorithm 安排数目
假设我们有n个元素,a1,a2,…,an,排列成一个圆圈。也就是说,a2在a1和a3之间,a3在a2和a4之间,an在an-1和a1之间,依此类推 每个元素的值可以为1或0。如果存在值不同的相应ai,则两种安排是不同的。例如,当n=3时,(1,0,0)和(0,1,0)是不同的排列,即使它们在旋转或反射下可能是同构的 因为有n个元素,每个元素可以取两个值,所以排列的总数是2n 问题是: 有多少种排列是可能的,以至于没有两个相邻的元素都具有值1?如果有帮助,只考虑n>3的情况。 我提出这个问题有几个原因:Algorithm 安排数目,algorithm,math,Algorithm,Math,假设我们有n个元素,a1,a2,…,an,排列成一个圆圈。也就是说,a2在a1和a3之间,a3在a2和a4之间,an在an-1和a1之间,依此类推 每个元素的值可以为1或0。如果存在值不同的相应ai,则两种安排是不同的。例如,当n=3时,(1,0,0)和(0,1,0)是不同的排列,即使它们在旋转或反射下可能是同构的 因为有n个元素,每个元素可以取两个值,所以排列的总数是2n 问题是: 有多少种排列是可能的,以至于没有两个相邻的元素都具有值1?如果有帮助,只考虑n>3的情况。 我提出这个问题有几个
让我们首先问一个问题“有多少长度为n的0-1序列没有两个连续的1?”让答案为A(n)。我们有A(0)=1(空序列),A(1)=2(“0”和“1”),和A(2)=3(“00”,“01”和“10”,但不是“11”) 为了便于编写递归,我们将a(n)计算为两个数字的和:
B(n),以0结尾的此类序列的数量,和
C(n),以1结尾的序列数 然后B(n)=A(n-1)(取任意长度为n-1的序列,并附加一个0)
C(n)=B(n-1)(因为如果在位置n处有一个1,那么在位置n-1处必须有一个0。)
这就给出了A(n)=B(n)+C(n)=A(n-1)+B(n-1)=A(n-1)+A(n-2)。 现在应该很熟悉了:-) A(n)是简单的斐波那契数Fn+2,其中斐波那契序列由F0=0、F1=1和Fn+2=Fn+1+Fn定义≥ 0.
现在回答你的问题。我们将分别计算a1=0和a1=1的排列数。对于前者,a2…an可以是任何序列(没有连续的1),因此数字是A(n-1)=Fn+1。对于后者,我们必须有a2=0,然后a3…an是没有以0结尾的连续1s的任何序列,即B(n-2)=a(n-3)=Fn-1 所以答案是Fn+1+Fn-1。 事实上,我们可以走得更远。请注意,如果您将答案称为
G(n)=Fn+1+Fn-1,则
G(n+1)=Fn+2+Fn和
G(n+2)=Fn+3+Fn+1,所以即使是G(n)也满足与斐波那契序列相同的递归性![事实上,任何类似斐波那契序列的线性组合都会满足相同的递归,所以这并不奇怪。]因此,计算答案的另一种方法是:
G(2)=3
G(3)=4
对于n,G(n)=G(n-1)+G(n-2)≥四, 现在还可以使用Fn=(αn-βn)/(α-β)(其中α和β为(1±)√5) /2,x2-x-1的根=0),以获得
G(n)=(1+√5) /2)n+((1)-√5) /2)n.
[您可以忽略第二项,因为对于大n,它非常接近0,事实上G(n)是最接近((1)的整数+√5) /2)n适用于所有n≥2.]
我决定编写一个小脚本来试用:
#!/usr/bin/python
import sys
# thx google
bstr_pos = lambda n: n>0 and bstr_pos(n>>1)+str(n&1) or ""
def arrangements(n):
count = 0
for v in range(0, pow(2,n)-1):
bin = bstr_pos(v).rjust(n, '0')
if not ( bin.find("11")!=-1 or ( bin[0]=='1' and bin[-1]=='1' ) ):
count += 1
print bin
print "Total = " + str(count)
arrangements(int(sys.argv[1]))
运行了5次,给了我11种可能性,100000,
00001,
00010,
00100,
00101,
01000,
01001,
01010,
10000,
10010,
10100
请原谅上面代码中的not()。将我的天真脚本加入其中。缓存部分结果的机会很多,但对于小n来说,它的运行速度足够快,所以我不必费心
def arcCombinations(n, lastDigitMustBeZero):
"""Takes the length of the remaining arc of the circle, and computes
the number of legal combinations.
The last digit may be restricted to 0 (because the first digit is a 1)"""
if n == 1:
if lastDigitMustBeZero:
return 1 # only legal answer is 0
else:
return 2 # could be 1 or 0.
elif n == 2:
if lastDigitMustBeZero:
return 2 # could be 00 or 10
else:
return 3 # could be 10, 01 or 00
else:
# Could be a 1, in which case next item is a zero.
return (
arcCombinations(n-2, lastDigitMustBeZero) # If it starts 10
+ arcCombinations(n-1, lastDigitMustBeZero) # If it starts 0
)
def circleCombinations(n):
"""Computes the number of legal combinations for a given circle size."""
# Handle case where it starts with 0 or with 1.
total = (
arcCombinations(n-1,True) # Number of combinations where first digit is a 1.
+
arcCombinations(n-1,False) # Number of combinations where first digit is a 0.
)
return total
print circleCombinations(13)
这个问题很类似于。由于循环约束,我找不到一个明显的方法来应用Zeckendorf定理,但Fibonacci数在这个问题中显然非常普遍。只是澄清一下,圆圈进入定义相邻的含义——元素n与元素1相邻,但不考虑相同位模式的旋转是相同的。是吗?用手检查2,3,4。我认为关于构造B(n)和C(n)的论点通过从长度为1的两种情况中进行推导来强制证明端点的正确性。参见“对于后者,我们必须有a2=0,然后a3…an是没有以0结尾的连续1的任何序列”这就是我认为序列不能在1开始和结束的地方。对“理论”(另一个答案)的很强的确认,因为f(6)=8和f(4)=3,所以G(5)=f(6)+f(4)确实是11:-)