大数乘法的模

Modulo of multiplication of large numbers

本文关键字:      更新时间:2023-10-16

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

这里的基本思想是首先定义一个非溢出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 .

注意:此代码未优化。

我认为您可以将 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).

施拉格的伎俩,由另一张海报建议,听起来像是一个更好的交易,但我不明白。 希望海报回来并完成他的回答!

相关文章:
  • 没有找到相关文章