最快的整数搜索任意X和Y

问题描述

借助离散数学的应用,python中解决此问题的最快算法是什么:

使用等式 ax + by = d ,其中 a,b d 是用户输入,在| L范围内搜索 x和y 的整数对, R | (包括 L和R )满足方程式。

L和R 也是用户输入。

按升序输出 x和y 的所有可能值。如果没有可能的配对,则打印

情况1:

a = 1
b = 5
d = 40
L = 0
R = 10

Result:
0 8
5 7
10 6

情况2:

a = 14
b = 91
d = 53
L = 1
R = 100

Result:
none

这是我的代码,但我认为搜索的方法快得多。这太低效了。

a = int(input())
b = int(input())
d = int(input())
L = int(input())
R = int(input())

isNone = True
for x in range(L,R+1):
    for y in range(L,R+1):
        if (a*x) + (b*y) == d:
            print(x,y)
            isNone = False
if isNone: print("none")

是否可以使用 O(1) 算法?最快的方法是什么?

解决方法

我想您要应用的身份如下(直接来自维基百科,尽管在大多数离散的数学课本中也可以找到类似的措词,或者可以自己证明):

最简单的线性Diophantine方程采用ax + by = c的形式,其中a,b和c为整数。解决方案由以下定理描述:

仅当c是a和b的最大公约数的倍数时,该Diophantine方程才具有解(其中x和y是整数)。此外,如果(x,y)是一个解,则其他解的形式为(x + kv,y-ku),其中k是任意整数,u和v分别是a和b的商通过a和b的最大公约数。

这几乎立即回答了这个问题,特别是因为它的标准证明使用了称为“欧几里得算法”的东西。为了简单起见,我们将执行以下操作:

  1. 在向前方向上使用欧几里得算法来找到g = gcd(a,b)
  2. 通过欧几里得算法反求解以找到_x,_y这样的_x*a + _y*b == g
  3. 如果d不是g的倍数,则不可能有任何解决方案,因此请尽早退出。
  4. 否则,x,y = _x*(d//g),_y*(d//g)是可能的解决方案。使用它来查找所需范围内的所有解决方案。
def gcd(a,b):
    # forward euclidean algorithm
    q,r,x,qs = None,b,a,[]
    while x%r:
        (q,r),x = divmod(x,r
        qs.append(q)

    # save the gcd for later
    g = r

    # backsolve euclidean algorithm
    if not qs:
        return 1,1-a//b,g
    theta,omega = 1,-qs[-1]
    for q in reversed(qs[:-1]):
        theta,omega = omega,theta - q * omega
    
    # theta * a + omega * b == g
    # g might be negative,but we don't care about a canonical solution
    return theta,omega,g

def idivide_zero(a,b):
    # integer division a/b,round toward 0 instead of round down
    q = a // b
    if q < 0 and b*q != a:
        q += 1
    return q

def bounded_solutions(a,d,L,R):
    _x,_y,g = gcd(a,b)
    if d%g:
        return

    # a*x + b*y == d
    x,_y*(d//g)

    # solutions are of the form (x+k*v,y-k*u)
    u,v = a//g,b//g

    # The next trick is to find all solutions in [L,R].
    # Basically,we need L <= x+k*v <= R and L <= y-k*u <= R.
    # Note that valid choices of k exist in a contiguous interval,so
    # we only have to find the lower and upper bounds to be able to
    # quickly enumerate all options.
    xb = sorted(idivide_zero(b-x,v) for b in (L,R))
    yb = sorted(idivide_zero(y-b,u) for b in (L,R))
    m,M = min(xb[0],yb[0]),max(xb[1],yb[1])
    for k in range(m,M+1):
        yield x+k*v,y-k*u

a = int(input())
b = int(input())
d = int(input())
L = int(input())
R = int(input())

empty = True
for x,y in bounded_solutions(a,R):
    print(x,y)
    empty = False
if empty:
    print('none')

代码未经测试。本质上是正确的,但是可能还需要进行一些调试。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...