给定N个整数的固定数组A,其中N <= 100,000且阵列的所有元素也小于或等于100,000。 A中的数字不是单调增加或连续或以其他方便组织的。
现在我被给予100,000个{V,L,R}形式的查询,其中在每个查询中我需要找到最大数A [i],其中i在[L,R]范围内不是互质的具有给定值V.(即GCD(V,A [i])不等于1.)
如果不可能,那么也要告诉你给定范围内的所有数字都与V互质。
一种基本方法是从L和R之间的每个A [i]迭代并用值V计算GCD,从而找到最大值。但如果查询的数量也可以达到100,000,那么有没有更好的方法呢?在这种情况下,每次检查每个数字的效率太低。
示例:
说明:
GCD(2,2)=2
GCD(2,3)=1
GCD(2,4)=2
GCD(2,5)=1
所以最大值是4。
答案 0 :(得分:0)
由于您有一个大型数组但只有一个V
,因此通过分解V
开始应该更快。之后,你的互质测试变得简单地找到每个独特因子V
的模数。
答案 1 :(得分:0)
让我们说
V = p_1*...*p_n
其中p_i是素数(您可以将其限制为不同的素数)。现在答案是
result = -1
for p_i:
res = floor(R / p_i) * p_i
if res >= L and res > result:
result = res
因此,如果您能快速分解V
,那么这将非常有效。
编辑我没有注意到数组不必包含所有整数。在那种情况下,筛选它,即给定素数p_1,...,p_n创建一个&#34;反转&#34;筛(即[L, R]
范围内的所有素数倍数)。然后你可以只用你的初始数组做一个筛子的交叉点。
EDIT2 要生成所有倍数的集合,您可以使用此算法:
primes = [p_1, ..., p_n]
multiples = []
for p in primes:
lower = floor(L / p)
upper = floor(R / p)
for i in [lower+1, upper]:
multiples.append(i*p)
从数学上可以看出,V
与[L, R]
中 multiples
范围内的每个数字相互联系。现在你只需:
solution = -1
for no in initial_array:
if no in multiples:
solution = max(solution, no)
请注意,如果您将result
设置为一组,则if no in result:
检查为O(1)
。
示例让我们说V = 6 = 2*3
和initial_array = [7,11,12,17,21]
以及L=10
和R=22
。让我们从倍数开始。按照算法我们得到
multiples = [10, 12, 14, 16, 18, 20, 22, 12, 15, 18, 21]
前7是2的倍数(范围[10,22]),后4是3的倍数(范围[10,22])。由于我们处理集合(std::set
?),因此不会有重复项(12和18):
multiples = [10, 12, 14, 16, 18, 20, 22, 15, 21]
现在浏览initial_array
并查看multiples
中的值。我们得到的最大数字是21
。确实21
与6
不相同。
答案 2 :(得分:0)
Daniel Bernstein的"Factoring into coprimes in essentially linear time"(Journal of Algorithms 54:1,1-30(2005))回答了一个类似的问题,用于识别Nadia Heninger "New research: There's No Need to Panic Over Factorable Keys--Just Mind Your Ps and Qs"`的不良(重复因子)RSA模型。问题在于找到一大堆非常大的数字之间的共同因素,而不是一次一对。
答案 3 :(得分:0)
对每个A元素进行因子分析,并为每个可能的素数因子存储包含该因子的数字的排序列表。
如果数字n包含O(log n)素因子,则此列表将使用O(N log N)内存。
然后,对于每个查询(V,L,R),在V中搜索每个素数因子,在[L,R]中包含该因子的最大数量是多少(这可以通过简单的二进制搜索来完成)