C++ 大数乘法模

C++ 大数乘法模,c++,math,multiplication,modulo,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的正确值?这里的基本思想是首先定义一个非溢出addmod函数,该函数在其算术中利用负数。然后根据它定义timesmod,同时使用位操作。时间复杂度为O(N),其中N是使用的位数(在本例中为64) 这很容易确认,因为A=-2和B=

是的,我知道这个问题可能看起来很幼稚,但我在谷歌和这个网站上搜索了很多,但没有找到令人满意的答案。 我只想计算(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)

这很容易确认,因为
A=-2
B=-1
mod
M


注意:此代码未经优化。

我认为您可以将128位乘积分成两部分(高64位和低64位),并将每一部分的模p减小。假设
p
约为
4^k
,然后除以
hi64/(p>>k)
,可以大致计算出这个数字中有多少个p;这将为您提供关于正确答案的
k-1
位。从整个事件中减去那么多的
p
,现在
hi64
k-1
位减少了。再次执行此操作,但要计算
(hi64>k)
。然后再做一次,计算
(hi64>k)


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

马特:我不同意dup的说法。虚幻灵魂:AB=(A-X)*B+XB,你总是可以用这种方式将A拆分成更小的数字。例如,设置X=地板(A/2)。如果子结果仍然太大,则可以应用相同的过程。这是被接受答案的人的评论“如果long的最大值为2^63-1,那么1768431*x不会溢出,只要x<290331368171”。但这正是我的疑问,如果A*B溢出怎么办,换句话说,除以etimpera@Cheersandhth.-阿尔夫:一个好朋友。这种方法似乎很有希望。我一定会调查的,而不是像OP所说的那个100000007版的问题。其他问题的答案没有一个是完全合适的,因为它们都建议只使用GMP或做一些缓慢、错误或特定于x86的事情。所有人都应该将此项保留为打开状态。问题是您正在为
BigInt
使用有符号类型,因此无法可靠地检测溢出(它会导致未定义的行为)。您需要使用无符号类型来获得可靠的溢出行为。@chrisdd您完全正确;谢谢你指出这一点。我已经更新了
addMod
函数来解决这个问题。您的方法与我编写的最后一个方法几乎相同:
long long int multiply(long long a,long long b,long long mod){long long long result;if(b==0)返回0LL;result=multiply(a,b>>1,mod);result=(result+result)%mod;if(b&1)result=(result+a)%mod;return result;}
@unrealsoul007我得到
乘法(0x7FFFFFFFFFFF01,0x7FFFFFFFFFFF02,0x7fffffffffffff03)
返回
-9223372036854711038
。你得到了什么?(我相信答案应该是
2
)@Matt只需编辑一点代码,用无符号的long-long替换long-long,就可以得到ans 2。
#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