C ++随机幂序列的最后一位

时间:2018-12-13 01:16:37

标签: c++ math integer-arithmetic

我意识到已经有几个主题涉及到这一点。但是我的问题不是关于如何构建这样的算法,而是要查找我在实现中犯了什么错误,从而导致数十个测试中的一个失败。

挑战:随机提供std::list<int>个随机数,确定x1 ^ (x2 ^ (x3 ^ (... ^ xn)))的最后一位。这些数字足够大,或者列表足够长,因此结果是天文数字,无法用传统方法处理。

我的解决方案:我选择使用模块化算术方法。简而言之,这些巨大功效的最后一位与降低的功效相同,后者由底数的第一位(模数10)组成,升至指数的最后两位数(模数100)。幂序列中的单位最多以4的模式重复,因此我们可以使用mod 4减少指数,将其偏移4以避免余数为0。至少,这是我到目前为止对以下内容的理解资源:brilliant / quora

#include <list>
#include <cmath>

int last_digit(std::list<int> arr)
{
  // Break conditions, extract last digit
  if (arr.size() == 1) return arr.back() % 10;
  if (arr.size() == 0) return 1;

  // Extract the last 2 items in the list
  std::list<int> power(std::prev(arr.end(), 2), arr.end());
  arr.pop_back(); arr.pop_back();

  // Treat them as the base and exponent for this recursion
  long base = power.front(), exponent = power.back(), next;

  // Calculate the current power
  switch (exponent)
  {
    case  0: next = 1; break;
    case  1: next = base % 100; break;
    default: next = (long)std::pow(base % 10, exponent % 4 + 4) % 100;
  }
  if (base != 0 && next == 0) next = 100;

  // Add it as the last item in the list
  arr.push_back(next);

  // Recursively deal with the next 2 items in the list
  return last_digit(arr);
}

随机例子:123,232 694,027 140,249 ≡8

  • 第一次复赛:{ 123'232, 694'027, 140'249 }
    • 基数:694,027 mod 10 = 7
    • 指数:140,249 mod 4 + 4 = 5
    • 下一个:7 5 = 16,807 mod 100 = 7
  • 第二次递归:{ 123'232, 7 }
    • 基数:123,232 mod 10 = 2
    • 指数:7 mod 4 + 4 = 7
    • 下一个:2 7 = 128 mod 100 = 28
  • 第三次递归:{ 28 }
    • 返回:28 mod 10 = 8

问题:这适用于数十个测试用例(如上面的一个),但对于2个 2 101 2 ≡6.
手动:

  • 101 2 = 10,201
  • 2 10,201 mod 4 = 0,+ 4 = 4
  • 2 4 = 16 // 6 -correct

但是,遵循以下算法:

  • 第一次递归:{ 2, 2, 101, 2 }
    • 基数:101 mod 10 = 1
    • 指数:2 mod 4 + 4 = 6
    • 下一个:1 6 = 1 mod 100 = 1
  • 第二个递归:{ 2, 2, 1 }(我们已经可以看到结果将是4)
    • 指数= 1,下一个= 2 mod 100 = 2
  • 第三次递归:{ 2, 2 }
    • 基数:2 mod 10 = 2
    • 指数:2 mod 4 + 4 = 6
    • 下一个:2 6 = 64 mod 100 = 64
  • 第四次递归:{ 64 }
    • 返回64 mod 10 = 4 // -wrong

从某种意义上说,我了解发生了什么,但我不确定为什么在这种特定情况下发生,而不是在其他数十种情况下发生。我承认我是在这里推销我的数学知识的极限,但是我得到的印象是我只是迷失了一小部分。

我认为这篇文章足够长而艰巨。如果有人对我要去哪里出错有任何见解,我将感谢一些提示。

1 个答案:

答案 0 :(得分:2)

关于一个非常大的数的模有很多问题,那里的许多sol'ns基本上都是基于基本数论的。 Fermat的小定理,中国余数定理和Euler的Phi函数都可以帮助您解决此类问题。我建议您阅读Victor Shoup撰写的“数论和代数的计算导论”。它可以帮助您更好地简化和更好地解决与数论相关的问题。 Here's the link for the book in case you'll browse this answer.