我在找到分裂模数时陷入了一个程序。
比如我说:
((a*b*c)/(d*e)) % n
现在,我不能简单地计算表达式,然后将其模数为n,因为乘法和除法在循环中进行,并且该值足够大,即使在long long中也不适合。
正如评论中所阐明的那样,n可以被认为是素数。
我发现,对于乘法,我可以很容易地将其计算为:
((a%n*b%n)%n*c%n)%n
但是无法理解如何计算除法部分。
我面临的问题是一个简单的例子:
((7*3*5)/(5*3)) % 11
上述表达式的值为7
但是如果我计算乘法,模数,那就像:
((7%11)*(3%11))%11 = 10
((10%11)*(5%11))%11 = 6
现在我剩下6/15,我无法生成正确的答案。
有人可以帮助我吗?请通过上面的例子让我理解逻辑。
答案 0 :(得分:5)
由于11是素数, Z 11 是一个字段。由于15 % 11
为4
,1/15
等于3
(因为3 * 4 % 11
为1)。因此,6/15
为6 * 3
,7
mod 11。
在你下面的问题评论中,你澄清模数永远是一个素数。
要有效地生成乘法逆的表,您可以将2
提升到连续的幂,以查看它生成的值。请注意,在字段 Z p 中,其中p是奇素数,2 p-1 = 1.因此,对于 Z 强> <子> 11 子>:
2^1 = 2
2^2 = 4
2^3 = 8
2^4 = 5
2^5 = 10
2^6 = 9
2^7 = 7
2^8 = 3
2^9 = 6
因此5
(2 4 )的乘法逆是2 6 (即9)。
因此,您可以像这样生成上表:
power_of_2[0] = 1;
for (int i = 1; i < n; ++i) {
power_of_2[i] = (2*power_of_2[i-1]) % n;
}
乘法逆表可以这样计算:
mult_inverse[1] = 1;
for (int i = 1; i < n; ++i) {
mult_inverse[power_of_2[i]] = power_of_2[n-1-i];
}
答案 1 :(得分:2)
在你的例子中,因为15 = 4 mod 11,你实际上最终必须评估(6/4)mod 11.
为了找到一个精确的解决方案,将其重新排列为6 =((x * 4)mod 11),这使得模数除法更加清晰。
如果没有别的,如果模数总是很小,你可以从0迭代到模数1来得到解。
请注意,当模数不是素数时,减少的问题可能有多种解决方案。例如,对于4 =((x * 2)mod 8)有两种解决方案:2和6.这将减少形式问题:
a = ( (x * b) mod c)
每当b和c不是相对素数时(即每当它们共用一个公约数时)。
类似地,当b和c不是相对素数时,可能没有解决减少问题的方法。例如,3 =((x * 2)mod 8)没有解决方案。只要b和c的最大公约数不分割a就会发生这种情况。
后两种情况是当n 不是素数时,从0到n-1 而不是在乘法下形成一个整数(或等效地,在+和*下面的一个字段)的整数的结果,而是简单地形成 ring 的不太有用的结构。
答案 2 :(得分:2)
我认为问题的方式,应该假设分子可以被分母整除。在这种情况下,素数n的有限域解和关于非素数n的可能扩展和注意的推测基本上是矫枉过正。如果您将所有分子术语和分母术语存储在数组中,则可以迭代地测试(分子术语,分母术语)对并快速找到最大公约数(gcd),然后将分子术语和分母术语除以gcd 。 (找到gcd是一个经典问题,你可以很容易地在线找到一个简单的解决方案。)在最坏的情况下,你将不得不迭代所有可能的对,但在某些时候,如果分母确实划分了分子,那么你最终会留下减少的分子项,所有分母项都是1.然后你就可以按照你描述的方式应用乘法(避免溢出)。
答案 3 :(得分:2)
当n为素数时,除以整数b只是乘以b的逆。那就是:
(a / b) mod n = (a * inv(b)) mod n
,其中
inv(b) = (b ^ (n - 2)) mod n
使用Exponentiation by squaring算法可以在O(log(n))时间内完成计算inv(b)。这是代码:
int inv(int b, int n)
{
int r = 1, m = n - 2;
while (m)
{
if (m & 1) r = (long long)r * b % n;
b = (long long)b * b % n;
m >>= 1;
}
return r;
}
为什么会这样?根据费马的小定理,如果n是素数,则对于任何正整数b,b ^(n - 1)mod n = 1。因此我们有inv(b)* b mod n = 1。
查找inv(b)的另一个解决方案是Extended Euclidean algorithm,需要更多代码才能实现。
答案 4 :(得分:0)
我认为你可以分发像
这样的部门z = d*e/3
(a/z)*(b/z)*(c/z) % n
仅保留整数除法问题。
答案 5 :(得分:0)
我认为你遇到的问题是你选择的问题太简单了。在那种情况下,答案是7,但如果a * b * c不能被c * d整除,怎么办?您应该首先查看如何使用模数进行除法,您应该清楚:)
答案 6 :(得分:0)
不是划分,而是用乘法反转来思考。对于mod-n系统中的每个数字,如果满足某些条件,则应该存在反转。对于d和e,找到那些反转,然后它们只是成倍增加。通过划分找不到反转!那里有很多信息......