大数乘法的模数

时间:2014-01-09 20:10:34

标签: c++ math multiplication modulo

是的我知道这个问题可能看起来很幼稚但我在谷歌和这个网站上搜索了很多但是找不到令人满意的答案。 我只想计算(A * B)%MOD,假设a长很长,那么b和MOD也是如此。 假设MOD大于A和B,使得A%MOD = A且B%MOD = B但A * B大于64位。如何计算(A * B)%MOD的正确值?

3 个答案:

答案 0 :(得分:2)

这里的基本思想是首先定义一个非溢出的addmod函数,该函数利用其算术中的负数。然后使用位操作定义timesmod。时间复杂度为O(N),其中N是使用的位数(在这种情况下为64)。

#include <iostream>
using namespace std;

typedef long long BigInt; // must be signed, to detect overflow

BigInt A = 0x7fffffffffffff01;
BigInt B = 0x7fffffffffffff02;
BigInt M = 0x7fffffffffffff03;

// For simplicity it is assumed x, y, and m are all positive.
BigInt addmod( BigInt x, BigInt y, BigInt m )
{
  x %= m;
  y %= m;
  BigInt sum = x-m+y; // -m <= sum < m-1
  return sum < 0 ? sum + m : sum;
}

BigInt timesmod( BigInt x, BigInt y, BigInt m )
{
  x %= m;
  y %= m;
  BigInt a = x < y ? x : y; // min
  BigInt b = x < y ? y : x; // max
  BigInt product = 0;
  for (; a != 0; a >>= 1, b = addmod(b,b,m) )
    if (a&1) product = addmod(product,b,m);
  return product;
}

int main()
{
  cout << "A = " << A << endl;
  cout << "B = " << B << endl;
  cout << "M = " << M << endl;
  cout << "A*B mod M = " << timesmod(A,B,M) << endl;
  return 0;
}

输出:

A = 9223372036854775553
B = 9223372036854775554
M = 9223372036854775555
A*B mod M = 2

A=-2B=-1 mod M以来,很容易确认。

注意:此代码未经过优化。

答案 1 :(得分:1)

我现在没有时间回答这个问题,所以我会给出一个指针然后再回来编辑这个答案。在您最喜欢的算法教科书(或搜索引擎)中查找“Schrage multiplication”。基本思路是将A和B分成几部分,分别处理,然后合并各部分以完成计算。

答案 2 :(得分:0)

我认为你可以将128位产品分成两部分(高64位和低64位)并减少每个模数p。假设p4^k附近,您可以通过除hi64 / (p>>k)来大致计算出此数字中有多少p?这应该给你大约k-1位的正确答案。从整个事物中减去许多p,现在hi64的位数减少k-1。再次执行此操作,但计算(hi64 << k-1) / (p >> k)。然后再做一次,计算(hi64 << k+k-2) / (p >> k)

另一张海报建议,施拉格的伎俩听起来更划算,但我不明白。希望海报回归并完成他的答案!