我有一个list
的整数,它在一个循环中不断被修改,我需要知道它的内容是否在经过一定的迭代后重复以打破循环。你知道吗
如果没有,则list
最终将修改为[]
,或者循环在达到某个迭代限制时终止。到目前为止,我的解决方案是:
def modify(numlist, a, b):
numlist = [(x * a) for x in numlist]
for i in range((len(numlist) - 1), 0, -1):
if numlist[i] >= b: numlist[i - 1] += numlist[i] // b
numlist[i] = numlist[i] % b
numlist[0] %= b
while numlist[-1] == 0:
numlist.pop(-1)
if numlist == []: break
numlist = [1, 2, 3, 4, 5]
listHistory = [numlist]
a, b = someValue, anotherValue
n = 0
while numlist != [] and n <= limit:
modify(numlist, int(a), int(b))
listHistory.append(numlist)
if numlist in listHistory: break
n += 1
limit
可能非常大(大约10**6
-10**7
),检查当前的numlist
和它以前的所有版本变得非常慢。你知道吗
有没有一种更有效的方法来实现这一点,或者甚至有一种方法来预先确定修改是否是通过列表的初始内容和给定的a
,b
来进行的?你知道吗
首先请允许我说,所有的列表都是周期性的,如果你考虑一个足够大的周期的话。你知道吗
也就是说,这可能是使用布卢姆过滤器的好地方,例如: https://pypi.python.org/pypi/drs-bloom-filter/
bloomfilters是一种集合,它可以非常快速地执行集合成员身份测试,并且可以在不实际存储元素数据的情况下向集合添加内容。这意味着它是概率的,但是你可以调整概率。在检测到bloom时,您可以使用一个快速检查算法来确认匹配,因此您可以使用一个确定的bloom+来检测结果。你知道吗
用法如下:
1000000是要存储在筛选器中的最大元素数,0.01是满时出现误报的最大概率。你知道吗
因此,您可以“存储”过滤器中的每个子序列,并快速检测复发。你知道吗
好的,有发现。 如果您查看列表中的最后一个元素,我们将其命名为
m
。它的情况是,它被a相乘,然后取模b。它从不与任何其他元素混合,因此,如果列表的配置必须重复自身,则必须满足以下条件:这是一个可以利用Fermats little theorem的问题 如果a和b是共数,那么
其中
phi
是Eulers toclient函数。你知道吗因此,这大大减少了必须存储在历史记录中的列表配置的数量。只需每隔
phi(b)
步存储一次。你知道吗我在这里找到了phi的一个实现: Computing Eulers Totient Function
更新:
好吧,我找到了一个快速的解决方法,如果你用
+= list[i] % b
代替+= list[i] // b
。否则在最坏的情况下需要b^4*phi(b)
步更新2:
我重写了
C
(见下文)中的代码,使之更快,并实现了@user2357112提出的“龟兔”算法。这样,我可以每秒检查大约一百万个循环,这应该比python实现快得多。 我尝试了一些不同的价值组合:所以你看到了它的发展方向:循环长度似乎总是
(b/GCD(b,a))^4*phi(b/GCD(n,a))
的除数,所以最坏的情况是(b/GCD(b,a))^4*phi(b/GCD(n,a))
步数你的
list
(顺便说一下,你真的应该重命名它)在baseb
中存储一个modb**something
数字。每次运行modify
都将数字乘以a
,然后在表示的末尾截断零。你知道吗调用最初由列表
n
表示的号码,并调用列表的原始长度l
。如果这个过程终止,它将在第一次迭代k
时这样做,使得b**l
除以n * a**k
,只有当且仅当b**l / gcd(n, b**l)
的所有素数因子都是a
的因子时才会发生。这很容易确定:相关问题 更多 >
编程相关推荐