给定一个数组,是否有可能在比O(N²)时间更好的时间内找到该数组的共质子数组?共素数组被定义为数组的连续子集,因此所有元素的GCD都是1.
答案 0 :(得分:1)
考虑在数组末尾添加一个元素。现在找到最右边的位置,如果有的话,从那个位置到你刚刚添加的元素的子数组是co-prime。因为它是最右边的,所以没有以添加的元素结尾的较短数组是共同素数。由于它是共同素数,因此每个从左边开始并以新元素结束的数组都是共同素数。所以你已经计算出以新元素结尾的共素子阵列的数量。如果你能有效地找到最合适的位置 - 例如在O(log n)而不是O(n) - 那么你可以通过在一个元素处扩展一个元素来计算O(n log n)中的共质子数组的数量。一段时间。
为了能够找到最右边的位置,可以将完整的数组视为完整二叉树的叶子,填充以使其长度为2的幂。在每个节点处将所有元素的GCD放在该节点下面 - 您可以从下到上在时间O(n)中执行此操作。数组中的每个连续间隔都可以由大小为O(log n)的节点集合覆盖,使得间隔由节点下面的叶子组成,因此您可以计算间隔的GCD是时间O(log n)。
要找到与当前元素形成共同主要子阵列的最右边位置,请从当前元素开始并检查它是否为1.如果是,则表示已完成。如果没有,请查看其左侧的元素,使用GCD,并将结果推送到堆栈。如果结果为1,则表示已完成,如果不是,则执行相同的操作,但查看是否存在可用于一次添加2个元素的2个元素的子树。在每个后续步骤中,您将要尝试查找的子树的大小加倍。你不会总是找到一个你想要的方便的子树,但是因为O(log n)子树可以覆盖每个间隔,你应该经常幸运地经历这个步骤的时间O(log n)。
现在你已经发现当前元素的整个数组不是co-prime,或者你找到了一个co-prime的部分,但是可能会比它需要的更进一步。堆栈顶部的值是通过获取堆栈上正下方的值的GCD和子树顶部的GCD来计算的。将它从堆栈中弹出并获取其下方和子树右半部分的值的GCD。如果你仍然是共同素数,那么你不需要子树的左半部分。如果没有,那么你需要它,但也许不是全部。在任何一种情况下,您都可以继续向下找到时间O(log n)中最右边的匹配。
所以我认为你可以找到最合适的位置与时间O(log n)中的当前元素形成一个共同的素数子阵列(诚然,有一些非常繁琐的编程)所以你可以及时计算互质子阵列的数量O(n log n)
两个例子:
列表1,3,5,7。下一级是1,1,根是1.如果当前元素是13,那么我检查7并发现gcd(7,13)= 1.因此我立即知道GCD(5,7,13)= GCD(3,5,7,13)= GCD(1,3,4,7,13)= 1.
列表2,4,8,16。下一级是2,8,根是2.如果当前的数字是32,那么我检查16并发现gcd(16,32)= 16!= 1所以然后我检查8并发现GCD(8,32)= 8然后我检查2并发现GCD(2,32)= 2因此在扩展数组中没有GCD = 1的间隔。 / p>