对于整数A> 0,B> 0,N> 0,找到整数x> 0,y> 0,使得N-(Ax + By)是最小的非负

时间:2016-10-21 03:39:46

标签: algorithm linear-algebra

示例:

  
    

A = 5,B = 2,N = 12

  

然后让x = 2,y = 1,所以12 - (5(2)+ 2(1))= 0.

另一个例子:

  
    

A = 5,B = 4,N = 12

  

这里x = 1,y = 1是最好的。注意x = 2,y = 0会更好,除了不允许x = 0。

我正在寻找快速的东西。

注意找到Ax + By的值就足够了。没有必要明确地给出x或y。

3 个答案:

答案 0 :(得分:3)

如果gcd(A,B)| N,那么N是你的最大值。否则,它是gcd(A,B)的最大倍数小于N.以4x + 2y = 13为例,该值为gcd(4,2)* 6 = 12实现由4(2)+2(2)= 12(在许多解决方案中)。

作为公式,您的最大值是Floor(N / gcd(A,B))* gcd(A,B)。

修改:如果x和y都必须为正数,则可能无效。但是,如果A + B> N,则甚至不会成为解决方案。这是一个适合你的算法...

from math import floor, ceil

def euclid_wallis(m, n):
    col1 = [1, 0, m]
    col2 = [0, 1, n]

    while col2[-1] != 0:
        f = -1 * (col1[-1] // col2[-1])
        col2, col1 = [x2 * f + x1 for x1, x2 in zip(col1, col2)], col2

    return col1, col2

def positive_solutions(A, B, N):
    (x, y, gcf), (cx, cy, _) = euclid_wallis(A, B)

    f = N // gcf
    while f > 0:
        fx, fy, n = f*x, f*y, f*gcf

        k_min = (-fx + 0.) / cx
        k_max = (-fy + 0.) / cy

        if cx < 0:
            k_min, k_max = k_max, k_min

        if floor(k_min) + 1 <= ceil(k_max) - 1:
            example_k = int(floor(k_min) + 1)
            return fx + cx * example_k, fy + cy * example_k, n

        if k_max <= 1:
            raise Exception('No solution - A: {}, B: {}, N: {}'.format(A, B, N))

        f -= 1

print positive_solutions(5, 4, 12) # (1, 1, 9)
print positive_solutions(2, 3, 6) # (1, 1, 5)
print positive_solutions(23, 37, 238) # (7, 2, 235)

答案 1 :(得分:0)

一种蛮力O(N^2 / A / B)算法,用普通的Python3实现:

import math

def axby(A, B, N):
    return [A * x + B * y
            for x in range(1, 1 + math.ceil(N / A))
            for y in range(1, 1 + math.ceil(N / B))
            if (N - A * x - B * y) >= 0]

def bestAxBy(A, B, N):
    return min(axby(A, B, N), key=lambda x: N - x)

这符合你的例子:

In [2]: bestAxBy(5, 2, 12)
Out[2]: 12                  # 5 * (2) + 2 * (1)

In [3]: bestAxBy(5, 4, 12)
Out[3]: 9                   # 5 * (1) + 4 * (1)

答案 2 :(得分:0)

不知道可能是什么算法,但我认为你需要类似的东西(C#)

static class Program
{
    static int solve( int a, int b, int N )
    {
        if( a <= 0 || b <= 0 || N <= 0 )
            throw new ArgumentOutOfRangeException();
        if( a + b > N )
            return -1;  // Even x=1, y=1 still more then N

        int x = 1;
        int y = ( N - ( x * a ) ) / b;

        int zInitial = a * x + b * y;
        int zMax = zInitial;

        while( true )
        {
            x++;
            y = ( N - ( x * a ) ) / b;
            if( y <= 0 )
                return zMax;    // With that x, no positive y possible
            int z = a * x + b * y;
            if( z > zMax )
                zMax = z;   // Nice, found better
            if( z == zInitial )
                return zMax;    // x/y/z are periodical, returned where started, meaning no new values are expected
        }
    }

    static void Main( string[] args )
    {
        int r = solve( 5, 4, 12 );
        Console.WriteLine( "{0}", r );
    }
}