【问题标题】:How can I calculate (A*B)%C for A,B,C <= 10^18, in C++?如何在 C++ 中计算 A、B、C <= 10^18 的 (A*B)%C?
【发布时间】:2014-01-03 20:24:12
【问题描述】:

例如,A=10^17、B=10^17、C=10^18。
乘积 A*B 超过 long long int 的限制。
此外,写 ((A%C)*(B%C))%C 也无济于事。

【问题讨论】:

  • This question on MathOverflow 似乎相关
  • 您可以应用数学来查找快捷方式,尽管这不一定会让您找到适合 long long int 的数字(在这种情况下,我认为这不仅仅是因为结果可能是大至 10^18)。在这种情况下,您需要任意精度整数。对于像 10^18 这样的数字,显而易见的非最优算法应该足够了,无论基数如何,它都只有几十位数。

标签: c++ product long-integer modulo integer-arithmetic


【解决方案1】:

假设您希望保持在 64 位整数运算范围内,您可以使用二进制长除法,这归结为一堆加法和乘以两个操作。这意味着您还需要这些运算符的防溢出版本,但这些都相对简单。

这里是一些 Java 代码,假设 A 和 B 已经是正数并且小于 M。如果不是,很容易预先使它们如此。

// assumes a and b are already less than m
public static long addMod(long a, long b, long m) {
    if (a + b < 0)
        return (a - m) + b;  // avoid overflow
    else if (a + b >= m)
        return a + b - m;
    else
        return a + b;
}

// assumes a and b are already less than m
public static long multiplyMod(long a, long b, long m) {
    if (b == 0 || a <= Long.MAX_VALUE / b)
        return a * b % m;   // a*b > c if and only if a > c/b
    // a * b would overflow; binary long division:
    long result = 0;
    if (a > b) {
        long c = b;
        b = a;
        a = c;
    }
    while (a > 0) {
        if ((a & 1) != 0) {
            result = addMod(result, b, m);
        }
        a >>= 1;
        // compute b << 1 % m without overflow
        b -= m - b; // equivalent to b = 2 * b - m
        if (b < 0)
            b += m;
    }
    return result;
}

【讨论】:

  • C++ 代码几乎相同,将long 更改为long longLong.MAX_VALUE 更改为std::numeric_limits&lt;long long&gt;::max()
【解决方案2】:

你可以使用

如果您只使用 10 的幂,您可以创建一个包含 2 个成员的简单类:一个基数和 10 的幂,因此 A=10^17 将是 {1, 17}。实现加减乘除非常简单,打印也很简单。

【讨论】:

    猜你喜欢
    • 2015-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-01
    • 2011-05-30
    • 2015-06-12
    • 2021-12-27
    • 1970-01-01
    相关资源
    最近更新 更多