【问题标题】:Avoid int overflow when doing a large multiplication进行大乘法时避免 int 溢出
【发布时间】:2017-11-11 19:57:47
【问题描述】:

我正在接受参加编程比赛的训练,所以我正在努力适应这类问题中的常见问题。我遇到了一些特别的问题:由于数字非常大而导致 int 溢出,我想知道如何解决这个特殊问题:Amelia and Rabbit Island。这是我的代码:

#include <iostream>

int main(){

   unsigned long long int a,b,c;
   int t;

   int nweeks;

   std::cin >> t;

   int **lines = new int*[t];
   for (size_t i = 0;i<t;i++)
      lines[i] = new int[3];

   for(size_t i=0;i<t;i++)
      for(size_t j=0;j<3;j++)
         std::cin >> lines[i][j];  


   for (size_t i=0;i<t;i++){
      a = lines[i][1];
      b = lines[i][2];
      const unsigned int mod = 1000000;
      for (size_t j=0;j<lines[i][0] - 2;j++){

         if (j > 0){
            c = a;
            a = a * b % mod;
            b = c;

         }
         else {
            a = a * b;
         }
      }

      nweeks = (lines[i][0] * 3) - 2;

      std::cout << "At week " << nweeks << " we obtain " << a%mod << " new rabbits.\n";
   }


   for (size_t i=0;i<t;i++)
      delete[] lines[i];

   delete[] lines;
   return 0;
}

在问题中它说答案必须用 mod(1000000) 表示,这应该避免溢出,但我就是找不到让它工作的方法,我的解决方案适用于正常值,但是比如输入的具体情况:

1 1000 10 10

这是单个案例允许的最大输入,我得到的输出是:

在第 2998 周,我们获得了 0 只新兔子。 这是错误的,都是因为 int 在乘法中溢出。

提前致谢。

编辑:嗯,由于某种原因,评估系统现在接受 mi 解决方案 -.-,无论如何谢谢。

【问题讨论】:

  • 那个问题有一个不寻常的选择使用1000000。这些问题大多数都是用1000000007完成的,这是一个只需要30位的素数,它允许两个数字模1000000007相加而不会溢出32位无符号整数,乘法通常在做 mod 1000000007 之前使用 64 位无符号乘积完成。

标签: c++ modulo integer-overflow


【解决方案1】:

您的输入选择不正确。

如果添加几行以输出ab 作为for 循环的最后几行,

std::cout << "a: " << a << "\n";
std::cout << "b: " << b << "\n";

您可以跟踪ab 的值如何变化。

通过使用1 10 10 10 作为输入,我得到以下输出:

a: 100
b: 10
a: 1000
b: 100
a: 100000
b: 1000
a: 0
b: 100000
a: 0
b: 0
a: 0
b: 0
a: 0
b: 0
a: 0
b: 0
At week 28 we obtain 0 new rabbits.

之后,ab 将继续为零。答案并没有错。输出模数 100000 确实为零。

通过使用1 10 8 8 作为输入,我得到以下输出:

a: 64
b: 8
a: 512
b: 64
a: 32768
b: 512
a: 777216
b: 32768
a: 813888
b: 777216
a: 775808
b: 813888
a: 821504
b: 775808
a: 375232
b: 821504
At week 28 we obtain 375232 new rabbits.

即使两组结果都正确,看起来也更容易接受。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-27
    • 1970-01-01
    相关资源
    最近更新 更多