最长的满意连续子阵列

时间:2013-12-17 13:26:53

标签: algorithm

A是一个数组,B是A,size(A)=N (1<=N<=30000)size(B)=M (1<=M<=30)中所有元素的素因子顺序,问题是找到最长的连续子数组,其累积是一个平方数。接下来是一个例子

 Input(condition):
     A={4,9,25,6}     B={2,3,5}       size(A)=N=4      size(B)=M=3
 Output:
     {4,9,25}
 Reason:
     the continuous subarray's accmulate must be a square number, so in A, there 6 subarraies,
    {4}           4=2^2
    {9}           9=3^2
    {25}          25=5^2
    {4,9}         4*9=6^2
    {9,25}        9*25=15^2
    {4,9,25}      4*9*25=30^2
    but we want find the longest one, that means the size of subarray must be bigest, so the result is {4,9,25}.

到目前为止我没有想过,所以没有成就,但我保证我已经考虑了很长时间,希望有所帮助,谢谢!

2 个答案:

答案 0 :(得分:0)

这不是整个答案,但它应该让你前进:

如果每个素数因子都是偶数次,则累积是一个平方数。

因此,对于每个可能的子阵列,计算yeach素因子的出现次数。如果每个因子的出现是偶数,那么子阵列的累积是一个平方数。

优化提示:

对于优化的解决方案,将质因数分解存储为32位数字,其中bit = 1表示奇数,bit = 0表示偶数,然后XOR:将它们组合在一起。如果总数为0,那么累积是一个平方数。

答案 1 :(得分:0)

我将向KlasLindbäck的回答添加一些细节,并提出一个可能的解决方案。

首先,我们将产品累积到位置i并将素因子分解存储在数组partialPrimes中。该数组仅包含指数是偶数(0)还是奇数(1)作为KlasLindbäck建议的位字段。

因此partialPrimes[0]将包含A[0]的分解。 partialPrimes[1]将包含A[0] * A[1]的分解等等。

此外,我们存储了给定分解的最大索引的映射。

int partialPrimes[N]
lastPartialPrimes := 0
maxPrime = new Map<int, int>
for i from 0 to N - 1
    int primes = calculatePrimeDecomposition(A[i], B)
    partialPrimes[i] = lastPartialPrimes xor primes
    lastPartialPrimes = primes
    maxPrime[primes] = i
next

可以通过连续除以给定的素因子并对相应的位进行xor来找到素数分解。

现在检查所有因子是否都有指数(因此如果数字是一个平方数),我们可以简单地将分解比较为0.

为了得到部分积的分解,我们可以减去相应指数的分解。所以例如要计算产品A[4] * A[5] * A[6] * A[7]的分解,我们可以计算partialPrimes[7] - partialPrimes[3](结束时的索引 - 之前的索引)。

因此,要找到产品为方数的范围,我们需要找到相等的partialPrimes

int maxLength = -1
int start = -1, end = -1
for i from 0 to N - 1
    //check if this product is already a square number
    if(partialPrimes[i] == 0 && maxLength < i + 1) 
    {
        maxLength = i + 1
        start = 0
        end = i
    }
    //is there a equal decomposition?
    else if maxPrime.contains(partialPrimes[i])
    {
        int newEnd = maxPrime[partialPrimes[i]]
        int newStart = i + 1
        int newLength = newEnd - newStart + 1
        if(newLength > maxLength)
        {
            start = newStart
            end = newEnd
            maxLength = newLength
        }
    }
next

该代码仅用于说明整体构思,可能包含轻微错误。

如果我们假设素因子分解需要O(d)时间,则该算法的总时间复杂度为O(n * d)