进行大型乘法时避免int溢出

时间:2017-11-11 19:57:48

标签: c++ modulo integer-overflow

我参加编程比赛的培训,所以我试图在这类问题上习惯常见的事情。我特别遇到了一些问题:由于数字太大而导致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解决方案-.-,无论如何,谢谢。

1 个答案:

答案 0 :(得分: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.

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