有一个线性同余系统,我想确定它是否有解决方案。使用解决此类系统的简单算法是不可能的,因为答案可能呈指数级增长。
我得到的一个假设是,如果一致系统没有解,那么其中有两个相互矛盾。我不知道这是否成立,如果这样做会导致一个简单的O(n ^ 2 log n)算法,因为检查一对同余有一个解是否需要O(log n)时间。然而对于这个问题,我宁愿看到更接近O(n)的东西。我们可以假设没有模数超过10 ^ 6,特别是我们可以快速将它们全部考虑在内。我们甚至可以进一步假设所有模数的总和不超过10 ^ 6(但仍然,他们的产品可能很大)。
答案 0 :(得分:1)
正如您所怀疑的那样,有一种相当简单的方法可以确定同余集是否具有解决方案,而无需实际构建该解决方案。你需要:
x = a (mod n)
形式;从评论中,听起来好像你已经有了这个。n
分解为主要权力的乘积:n = p1^e1 * p2^e2 * ... * pk^ek
。x = a (mod n)
替换为同余x = a (mod pi^ei)
的集合,对于您在步骤2中找到的k
主要权力,每个同余一个。现在,Chinese Remainder Theorem足以独立检查每个素数的兼容性:给定任何两个同余x = a (mod p^e)
和x = b (mod p^f)
,当且仅当{{1}时,它们是兼容的}}。确定兼容性后,您可以在不丢失任何信息的情况下抛弃较小模数的同余。
使用正确的数据结构,您可以通过同余来完成所有这些:对于遇到的每个素数a = b (mod p^(min(e, f))
,您需要跟踪找到的最大指数p
远,连同相应的右侧(为方便起见,减少了模e
)。运行时间可能会受到模数因子分解的影响,但如果没有模数超过p^e
,那么通过预先建立10^6
范围内每个整数的映射,您也可以非常快速地完成该步骤。它最小的素因。
编辑:因为这应该是一个编程站点,这里有一些(Python 3)代码来说明上述内容。 (对于Python 2,将1 .. 10^6
调用替换为range
以提高效率。)
xrange
最后一点说明:在上文中,我们利用了模量很小的事实,因此计算主要功率因数并不是什么大问题。但是如果你做需要为更大的模数(数百或数千个数字)做这个,它仍然是可行的。您可以跳过因子分解步骤,而是找到模数集合的“互质基础”:即成对相对正整数的集合,这样您的同余中出现的每个模数都可以表示为一个乘积(可能重复) )该集合的元素。现在按上述步骤进行,但参考该互质基础而不是素数和主要权力集。请参阅Daniel Bernstein的this article,以获得计算一组正整数的互质基的有效方法。您可能最终会在列表中进行两个传递:一个用于计算互质基数,另一个用于检查一致性。