计算两位数的可能性

时间:2018-08-22 07:02:43

标签: algorithm

有两个变量:a和b。 a的初始值为1,b为0。 有两个按钮:红色和蓝色。红色按钮将b的值添加到a,蓝色按钮将a的值添加到b。

red : a = a+b 
blue: b = b+a

现在的问题是,如果在a上可以得到整数X,在b上可以得到Y。

例如,给您X = 7, Y=9.

您从a = 1,b = 0开始。 蓝色按钮两次将使b 0+1+1=2,而a保持不变。 然后红色按钮可以按下3次,1+2+2+2=7。 因此,a=7b=2,然后蓝色按钮可以使b 2+7=9。最后,a=7b=9

我如何计算使用这两个按钮获得X和Y的可能性?该算法必须适用于较大的数字(> 1000)

您不必知道按钮的路径即可获取数字,而只需了解各种可能性。

3 个答案:

答案 0 :(得分:1)

如果(X, Y)为正,一对X是可能的,并且XY的最大公约数为1。这相对容易证明:

  

首先请注意,如果可以使用X,Y,则gcd必须为1。   否则,请考虑gcd不等于的最小X,Y   1. XY都不能为0。但是最小的X,Y必须来自可能的X-Y,YX,Y-X,但是   两者的gcd与X,Y相同,并且都较小,这与我们的假设相矛盾   极简。

     

第二,假设X,Y的gcd等于1(0,1除外   这是唯一无法与gcd=1X=0配对的货币对。   考虑最小的X,Y。再说一遍,这一定是来自   X-Y,YX,Y-X都拥有gcd=1,然后我们又有了一个   极小假设的矛盾。

     

因此,我们证明了0,1除外,如果且仅当gcd(X,Y)=1   X,Y是否可达。

然后可以使用标准的gcd算法来计算答案:

def gcd(a, b):
    while b > 0:
        a, b = b, a % b
    return a

def solvxy(X, Y):
    return X>0 and gcd(X, Y)==1

答案 1 :(得分:0)

您可以从X,Y值展开(可能)解。

从较大的值中减去较小的值。

在平局的情况下:对于(1,1),存在解,对于较大的值-不。

如果达到(1,0)值-解决方案确实存在

X   Y    Sub    
7   9     x 
7   2     y
5   2     y
3   1     y
1   1     both x and y
for x:
1   0    !!! solution found

递归Python函数:

def solxy(aa, bb):
    if (aa < 1):
        return False
    if (bb == 0):
        return (aa == 1)
    if (aa == bb):
        return (aa == 1)
    elif (bb > aa):
        return solxy(aa, bb - aa)
    else:
        return solxy(aa - bb, bb)

print(solxy(7,9))
print(solxy(9,7))
print(solxy(3,3))
print(solxy(3,0))
print(solxy(0,3))
print(solxy(1,0))

True
True
False
False
False
True

修改:
迭代解决方案(使用@squeamish ossifrage提出的模运算):

def solxyit(aa, bb):
    while (aa > 1) and (bb > 1):
        if (bb > aa):
            bb %= aa
        else:
            aa %= bb
    return (aa == 1) or ((bb==1) and (aa>1))

答案 2 :(得分:0)

def two_digits(a, b):
    INIT_A = 1
    INIT_B = 0

    assert ( (type(a) == int or type(a) == long) and (type(b) == int or type(b) == long) )

    #print a, b

    if a == INIT_A and b == INIT_B:
        return True
    if a < INIT_A or b < INIT_B:
        return False

    if a == INIT_A:
        times = (b - INIT_B) / INIT_A;

        #print times, " press b"
        return (times * INIT_A + INIT_B == b)
    elif b == INIT_B:
        return False           #cause a > INIT_A, and INIT_B is 0, thus can't reach(a, INIT_B)
    else:
        if a > b:
            times = (a - INIT_A) / b
            return two_digits(a - times * b, b)
        elif a < b:
            times = (b - INIT_B) / a
            return two_digits(a, b - a * times)
        else:
            return two_digits(0, b) or two_digits(a, 0)

print two_digits(7, 9)
print two_digits(5000, 5003)