求解大数的线性方程

时间:2016-05-10 00:21:36

标签: python algorithm

我有static func createOrUpdate(dictionary:NSDictionary) -> Promise<Media> { // Query and update from any thread return Promise { fulfill, reject in executeInBackground { // c("BG media \(dictionary)") let realm:RLMRealm = RLMRealm.defaultRealm() realm.beginWriteTransaction() let media = Media.createOrUpdateInRealm(realm, withJSONDictionary:dictionary as [NSObject : AnyObject]) // media.type = type c("BG media \(media)") let mediaId = media.localIdentifier do { try realm.commitWriteTransaction() executeInForeground({ let mediaIdFG = mediaId.copy() as! String let newMedia = Media.findOneByLocalIdentifier(mediaIdFG) c("FG \(mediaIdFG) newMedia \(newMedia)") fulfill(newMedia) }) } catch { reject( Constants.createError("Realm Something went wrong!") ) } } } // return promise } // func createOrUpdate 形式的等式,其中a,b,c,d是大约1000位的已知数字,我需要求解n1。

我试过了:

a+b*n1=c+d*n2

,但这种方法对于这么大的数字来说太慢了。在这种情况下有没有更好的方法?

1 个答案:

答案 0 :(得分:1)

您希望horizontalx找到x = a (mod b)。那么,x = c (mod d)n1 = (x - a) / b

如果n2 = (x - c) / db是互质的,则Chinese Remainder Theorem保证d的存在 - 并且可以使用扩展欧几里得算法找到解决方案。

如果xb不是互质(即d},那么(注意gcd(b, d) != 1),我们可以减去a = c (mod gcd(b, d))从两边开始,按a % gcd(b, d)划分,以减少上述问题。

将其置于代码中

以下是使用此方法查找gcd(b, d)n1的代码:

n2

这里有一些测试代码可以运行1000个1000位输入的随机试验:

def egcd(a, b):
    if a == 0:
        return (b, 0, 1)
    else:
        g, y, x = egcd(b % a, a)
        return (g, x - (b // a) * y, y)

def modinv(a, m):
    return egcd(a, m)[1] % m

def solve(a, b, c, d):
    gcd = egcd(b, d)[0]
    if gcd != 1:
        if a % gcd != c % gcd:
            raise ValueError('no solution')
        a, c = a - a % gcd, c - c % gcd
        a //= gcd
        b //= gcd
        c //= gcd
        d //= gcd
    x = a * d * modinv(d, b) + c * b * modinv(b, d)
    return (x - a) // b, (x - c) // d

(注意,递增限制必须增加,因为实现Extended Euclidean算法的import sys sys.setrecursionlimit(10000) import random digit = '0123456789' def rn(k): return int(''.join(random.choice(digit) for _ in xrange(k)), 10) k = 1000 for _ in xrange(1000): a, b, c, d, = rn(k), rn(k), rn(k), rn(k) print a, b, c, d try: n1, n2 = solve(a, b, c, d) except ValueError, exn: print 'no solution' print continue if a + b * n1 != c + d * n2: raise AssertionError('failed!') print 'found solution:', n1, n2 print 函数是递归的,并且在1000位数字上运行它可能需要非常深的堆栈。

另请注意,这会在返回解决方案时检查结果。但是当一个!= c(mod gcd(b,d))并且引发​​了异常信号没有结果时,就不会进行检查。因此,当解决方案存在时,您需要仔细考虑是否无法找到结果。

这在我的机器上大约7-8秒内运行(1000次试验),因此它的表现相当不错。