简体   繁体   English

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

[英]How to optimize (3*O(n**2)) + O(n) algorithm?

I am trying to solve the arithmetic progression problem from USACO.我正在尝试解决 USACO 的算术级数问题。 Here is the problem statement.这是问题陈述。

An arithmetic progression is a sequence of the form a, a+b, a+2b, ..., a+nb where n=0, 1, 2, 3, ... .等差数列是 a, a+b, a+2b, ..., a+nb 形式的序列,其中 n=0, 1, 2, 3, ... 。 For this problem, a is a non-negative integer and b is a positive integer.对于这个问题,a 是一个非负整数,b 是一个正整数。

Write a program that finds all arithmetic progressions of length n in the set S of bisquares.编写一个程序,找出双平方集合 S 中所有长度为 n 的等差数列。 The set of bisquares is defined as the set of all integers of the form p2 + q2 (where p and q are non-negative integers).双平方集被定义为形式为 p2 + q2 的所有整数的集合(其中 p 和 q 是非负整数)。

The two lines of input are n and m, which are the length of each sequence, and the upper bound to limit the search of the bi squares respectively.输入的两行分别是n和m,分别是每个序列的长度,以及限制bi平方搜索的上限。

I have implemented an algorithm which correctly solves the problem, yet it takes too long.我已经实现了一个正确解决问题的算法,但它需要太长时间。 With the max constraints of n = 25 and m = 250, my program does not solve the problem in the 5 second time limit.在 n = 25 和 m = 250 的最大约束条件下,我的程序在 5 秒的时间限制内没有解决问题。

Here is the code:这是代码:

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))

The program outputs the correct answer, but it takes too long.程序输出正确答案,但耗时太长。 I tried running the program with the max n/m values, and after 30 seconds, it was still going.我尝试使用最大 n/m 值运行程序,30 秒后,它仍在运行。

Disclaimer: this is not a full answer.免责声明:这不是一个完整的答案。 This is more of a general direction where to look for.这更像是一个寻找的一般方向。

For each member of a sequence, you're looking for four parameters: two numbers to be squared and summed ( q_i and p_i ), and two differences to be used in the next step ( x and y ) such that对于序列的每个成员,您正在寻找四个参数:要平方和求和的两个数字( q_ip_i ),以及要在下一步中使用的两个差值( xy ),使得

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

Subject to:受制于:

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

There are too many unknowns so we can't get a closed form solution.有太多的未知数,所以我们无法得到一个封闭形式的解决方案。

  • let's fix b : (still too many unknowns)让我们修复b :(还有太多未知数)
  • let's fix q_i , and also state that this is the first member of the sequence.让我们修复q_i ,并声明这是序列的第一个成员。 Ie, let's start searching from q_1 = 0 , extend as much as possible and then extract all sequences of length n .即,让我们从q_1 = 0开始搜索,尽可能地扩展,然后提取所有长度为n序列。 Still, there are too many unknowns.尽管如此,还有太多的未知数。
  • let's fix x : we only have p_i and y to solve for.让我们修复x :我们只有p_iy来解决。 At this point, note that the range of possible values to satisfy the equation is much smaller than full range of 0..m .此时,请注意满足方程的可能值范围远小于0..m完整范围。 After some calculus, b = x*(2*q_i + x) + y*(2*p_i + y) , and there are really not many values to check.经过一些微积分, b = x*(2*q_i + x) + y*(2*p_i + y) ,要检查的值确实不多。

This last step prune is what distinguishes it from the full search.最后一步修剪是它与完整搜索的区别。 If you write down this condition explicitly, you can get the range of possible p_i values and from that find the length of possible sequence with step b as a function of q_i and x .如果你明确写下这个条件,你可以得到可能的p_i值的范围,并从中找到可能序列的长度,步骤b作为q_ix的函数。 Rejecting sequences smaller than n should further prune the search.拒绝小于n序列应该进一步修剪搜索。

This should get you from O(m**4) complexity to ~ O(m**2) .这应该让你从O(m**4)复杂性到 ~ O(m**2) It should be enough to get into the time limit.进入时间限制应该足够了。

A couple more things that might help prune the search space:还有一些可能有助于修剪搜索空间的事情:

b <= 2*m*m//n

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

An answer on math.stackexchange says that for a number x to be a bisquare, any prime factor of x of the form 3 + 4k (eg, 3, 7, 11, 19, ...) must have an even power. math.stackexchange上的一个答案说, 要使数字 x 成为双平方数,x 的任何形式为 3 + 4k(例如,3, 7, 11, 19, ...)的素因数必须具有偶数次幂。 I think this means that for any n > 3, b has to be even.我认为这意味着对于任何 n > 3, b必须是偶数。 The first item in the sequence a is a bisquare, so it has an even number of factors of 3. If b is odd, then one of a+1b or a+2b will have an odd number of factors of 3 and therefore isn't a bisquare.序列a的第一项是双方阵,因此它有偶数个 3 的因数。如果b是奇数,则a+1ba+2b中的一个将有奇数个因数为 3,因此不是' t 一个双方。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM