如何优化(3 * O(n ** 2))+ O(n)算法?

时间:2019-08-17 00:53:52

标签: python arrays loops optimization

我正在尝试解决USACO的算术级数问题。这是问题陈述。

  

算术级数是形式为a,a + b,a + 2b,...,a + nb的序列,其中n = 0、1、2、3,...。对于这个问题,a是一个非负整数,b是一个正整数。

     

编写一个程序,在双平方集S中找到所有长度为n的算术级数。双平方的集合定义为形式为p2 + q2的所有整数的集合(其中p和q为非负整数)。

     

输入的两行分别是n和m,它们分别是每个序列的长度,以及分别限制双平方搜索的上限。

我已经实现了一种可以正确解决该问题的算法,但是它花费的时间太长。在最大约束为n = 25和m = 250的情况下,我的程序在5秒的时间内没有解决问题。

代码如下:

n = 25
m = 250

bisq = set()
for i in range(m+1):
    for j in range(i,m+1):
        bisq.add(i**2+j**2)

seq = []
for b in range(1, max(bisq)):
    for a in bisq:
        x = a
        for i in range(n):
            if x not in bisq:
                break
            x += b
        else:
            seq.append((a,b))

程序输出正确的答案,但是花费的时间太长。我尝试以最大n / m值运行该程序,但30秒后,它仍在运行。

2 个答案:

答案 0 :(得分:1)

免责声明:这不是一个完整的答案。这更多的是在哪里寻找的一般方向。

对于序列的每个成员,您正在寻找四个参数:两个要求平方和的数字(q_ip_i),以及下一步要使用的两个差异( xy)这样

q_i**2 + p_i**2 + b = (q_i + x)**2 + (p_i + y)

受制于:

  • 0 <= q_i <= m
  • 0 <= p_i <= m
  • 0 <= q_i + x <= m
  • 0 <= p_i + y <= m

未知数太多,因此我们无法获得封闭式解决方案。

  • 让我们修复b :(仍然有很多未知数)
  • 让我们修复q_i,并声明它是序列的第一个成员。也就是说,让我们从q_1 = 0开始搜索,尽可能扩展,然后提取所有长度为n的序列。尽管如此,仍有太多未知数。
  • 让我们解决问题x:我们只有p_iy可以解决。此时,请注意,满足方程式的可能值范围比0..m的整个范围小得多。经过b = x*(2*q_i + x) + y*(2*p_i + y)演算后,实际上没有太多要检查的值。

最后一个修剪是它与完整搜索的区别所在。如果您明确记下此条件,则可以得到可能的p_i值的范围,并从中找到步骤b作为q_i和{{1的函数}}。拒绝小于x的序列应进一步简化搜索。

这应该使您从n的复杂性转到〜O(m**4)。进入时间限制应该足够了。

答案 1 :(得分:0)

还有其他一些事情可能会有助于缩小搜索空间:

b <= 2*m*m//n

a <= 2*m*m - b*n

math.stackexchange的回答说,要使x成为双平方,则x的任何素数形式3 + 4k(例如3、7、11、19,...)必须具有均匀的力量我认为这意味着对于任何n> 3,b必须是偶数。序列a中的第一项是双平方,因此其偶数因子为3。如果b为奇数,则a+1ba+2b中的一个将为具有3的奇数个因数,因此不是双平方。