我和我的兄弟讨论了一种快速而又脏的算法,用于改组一副牌(即每个元素都是唯一的阵列)。算法描述:
让牌组中的牌数为n
。取一个x
数字,以便gcd(n,x)=1
。现在迭代选择(x*i) mod n
的卡号i=1
,直至i=n
并将其放入新的一堆卡片中(没有从原始卡片中取出卡片,也就是说,复制一张卡片。新的一堆卡将是我们的结果。
我似乎很清楚,只执行一次这种算法不会产生“足够随机”的结果(在某种意义上,它将无法通过统计测试来确定随机性)。但是,如果我们迭代地执行算法,可能是为了满足x
的{{1}}的新值,该怎么办?如果这样做足够多次会给我们一个“足够随机”的结果,我们可以期望需要多少次这样做gcd(n,x)=1
的函数?
答案 0 :(得分:3)
由于模运算的奇迹,多次这样做是不够的。事实上,你可以用这种方式获得最多n
个排列,而且恰恰是n
为素数或1时。
假设您要两次执行此操作,x
第一次n
为y
,第二次n
为p
。
位置p * x (mod n)
上的元素第一次移至(p * x) * y (mod n)
。然后第二次移动到p * (x * y) (mod n)
。这与将其移动到x * y = v (mod n)
相同,因为模运算的关联性质。但是如果p * v (mod n)
那么它就像移动到n
一样 - 而且如你所知,它不会超过n
个等价类。
因此,最多n
个排列可能会产生n
长度的牌组。 (不,这不是一个严格的证明!)
修改强>
我声称如果你使用模乘法取幂,它会更优越。然而,在进一步考虑之后,许多琐碎的配置仍然会成为模块算术的牺牲品,并且在最多{{1}}个排列中#34;方式。