C 如何计算模数除法
在寻找除法模数时,我被困在一个程序中 比如说我有:C 如何计算模数除法,c,algorithm,C,Algorithm,在寻找除法模数时,我被困在一个程序中 比如说我有: ((a*b*c)/(d*e)) % n 现在,我不能简单地计算表达式,然后将其模化为n,因为乘法和除法是在循环中进行的,并且该值足够大,即使在长时间内也不适合 正如在评论中阐明的,n可以被视为素数 我发现,对于乘法,我可以很容易地计算出: ((a%n*b%n)%n*c%n)%n 但当时不知道如何计算除法部分 我面临的问题是举一个简单的例子: ((7*3*5)/(5*3)) % 11 上述表达式的值为7 但如果我计算乘法,模,它会像: (
((a*b*c)/(d*e)) % n
现在,我不能简单地计算表达式,然后将其模化为n,因为乘法和除法是在循环中进行的,并且该值足够大,即使在长时间内也不适合
正如在评论中阐明的,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了,我没有办法得出正确的答案
谁能帮帮我吗。请通过上面的例子让我理解逻辑。我想你可以像这样分配分区
z = d*e/3
(a/z)*(b/z)*(c/z) % n
只剩下整数除法问题。因为11是素数,Z11是一个字段。由于
15%11
是4
,1/15
等于3
(因为3*4%11
是1)。因此,6/15
是6*3
,这是7
11模
在问题下方的评论中,您阐明了模数始终是素数
要高效地生成乘法逆表,可以将2
提高到连续幂,以查看它生成的值。注意,在一个域Zp中,p是奇数素数,2p-1=1。因此,对于Z11:
所以5
(24)的乘法逆是26(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];
}
_2[0]=1的power_;
对于(int i=1;i
乘法逆表可以这样计算:
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];
}
mult_逆[1]=1;
对于(int i=1;i
我认为您遇到的问题是,您选择了一个太简单的问题作为示例。在这种情况下,答案是7,但是如果a*b*c不能被c*d平均整除呢?您可能应该首先查看如何使用模进行除法,这对您来说应该很清楚:)在您的示例中,由于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非的整数在乘法下形成一个群(或等价地,在+和*下形成一个域),而只是形成一个环的不太有用的结构 不要用除法,而要用乘法逆。对于mod-n系统中的每个数字,如果满足某些条件,则应该有一个倒数。对于d和e,求出这些倒数,然后它们都是相乘的。求逆不是除法!有很多信息…我认为这个问题的提问方式应该假设分子可以被分母整除。在这种情况下,质数n的有限域解和关于非质数n的可能扩展和警告的推测基本上是多余的。如果所有分子项和分母项都存储在数组中,则可以迭代测试(分子项、分母项)对,并快速找到最大公约数(gcd),然后将分子项和分母项除以gcd。(找到gcd是一个经典的问题,你可以很容易地在网上找到一个简单的解决方案。)在最坏的情况下,你必须迭代所有可能的对,但在某个点上,如果分母确实除以分子,那么你最终会得到减少的分子项,所有分母项都将为1。然后您就可以按照您描述的方式应用乘法(避免溢出)。因为n是素数,所以除以整数b就是简单地乘以b的逆。即:
(a / b) mod n = (a * inv(b)) mod n
在哪里
使用该算法可以在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模n=1
查找inv(b)的另一个解决方案是,它需要更多的代码来实现。为什么
/3
是答案的一部分?不,您必须执行立方根z=(d*e)**(1/3)
。(或者是C)但是n
不一定是素数。@iamnotmaynard:我没说这是一个通解,他想知道如何从他的例子中得出正确的答案。OP正在寻找一个通解。@iamnotmaynard:通解可能来自中国的余数定理,但我的数论在这一点上太生疏了。@PieterGeerkens:n
是素数,根据问题下的评论。a%n=a-(n*int(a/n))使用一个大整数库。(a/b)mod n=((a mod n)(1/b mod n)mod n)@Randy不能保证b
有一个逆模