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}.
到目前为止我没有想过,所以没有成就,但我保证我已经考虑了很长时间,希望有所帮助,谢谢!
答案 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)