Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何计算模数除法_C_Algorithm - Fatal编程技术网

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
有一个逆模