[英]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_i
和p_i
),以及要在下一步中使用的两个差值( x
和y
),使得
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.有太多的未知数,所以我们无法得到一个封闭形式的解决方案。
b
: (still too many unknowns)b
:(还有太多未知数)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.x
: we only have p_i
and y
to solve for.x
:我们只有p_i
和y
来解决。 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_i
和x
的函数。 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+1b
或a+2b
中的一个将有奇数个因数为 3,因此不是' t 一个双方。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.