简体   繁体   English

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

[英]C++ last digit of a random sequence of powers

I realise that there are several topics already covering this.我意识到已经有几个主题涵盖了这一点。 But my question is not regarding how to build such an algorithm, rather in finding what mistake I have made in my implementation that's causing a single test out of dozens to fail.但我的问题不是关于如何构建这样的算法,而是找出我在实施中犯了什么错误,导致几十个测试中的一个测试失败。

The challenge : supplied with a std::list<int> of random numbers, determine the last digit of x1 ^ (x2 ^ (x3 ^ (... ^ xn))) .挑战:提供随机数的std::list<int> ,确定x1 ^ (x2 ^ (x3 ^ (... ^ xn)))的最后一位。 These numbers are large enough, or the lists long enough, that the result is astronomical and cannot be handled by traditional means.这些数字足够大,或者列表足够长,结果是天文数字,无法通过传统方式处理。

My solution : I chose to use a modular arithmetic approach.我的解决方案:我选择使用模块化算术方法。 In short, the last digit of these huge powers will be the same as that of a reduced power consisting of the first digit of the base (mod 10), raised to the last two digits of the exponent (mod 100).简而言之,这些巨大幂的最后一位将与由基数的第一位 (mod 10) 提高到指数的最后两位 (mod 100) 的降低幂相同。 The units in a sequence of powers repeat in patterns of 4 at most, so we can use mod 4 to reduce the exponent, offset by 4 to avoid remainders of 0. At least, this is my understanding of it so far based on the following resources: brilliant / quora .幂序列中的单位最多以4的模式重复,所以我们可以使用mod 4来减少指数,抵消4以避免余数为0。至少,这是我目前基于以下内容的理解资源: 辉煌/ 法定人数

#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);
}

Random example : 123,232 694,027 140,249 ≡ 8随机示例:123,232 694,027 140,249 ≡ 8

  • First recrusion: { 123'232, 694'027, 140'249 }第一次召回: { 123'232, 694'027, 140'249 }
    • base: 694,027 mod 10 = 7基数:694,027 mod 10 = 7
    • exponent: 140,249 mod 4 + 4 = 5指数:140,249 mod 4 + 4 = 5
    • next: 7 5 = 16,807 mod 100 = 7下一个:7 5 = 16,807 模 100 = 7
  • Second recursion: { 123'232, 7 }第二次递归: { 123'232, 7 }
    • base: 123,232 mod 10 = 2基数:123,232 mod 10 = 2
    • exponent: 7 mod 4 + 4 = 7指数:7 mod 4 + 4 = 7
    • next: 2 7 = 128 mod 100 = 28下一个:2 7 = 128 模 100 = 28
  • Third recursion: { 28 }第三次递归: { 28 }
    • return: 28 mod 10 = 8返回:28 mod 10 = 8

The problem : this works for dozens of test cases (like the one above), but fails for 2 2 101 2 ≡ 6.问题:这适用于许多测试用例(如上面的那个),但对于 2 2 101 2 ≡ 6 失败。
By hand:用手:

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

Following the algorithm, however:然而,遵循该算法:

  • First recursion: { 2, 2, 101, 2 }第一次递归: { 2, 2, 101, 2 }
    • base: 101 mod 10 = 1基数:101 mod 10 = 1
    • exponent: 2 mod 4 + 4 = 6指数:2 mod 4 + 4 = 6
    • next: 1 6 = 1 mod 100 = 1下一个:1 6 = 1 模 100 = 1
  • Second recursion: { 2, 2, 1 } (we can already see that the result is going to be 4)第二次递归: { 2, 2, 1 } (我们已经可以看到结果将是 4)
    • exponent = 1, next = 2 mod 100 = 2指数 = 1,下一个 = 2 mod 100 = 2
  • Third recursion: { 2, 2 }第三次递归: { 2, 2 }
    • base: 2 mod 10 = 2基数:2 mod 10 = 2
    • exponent: 2 mod 4 + 4 = 6指数:2 mod 4 + 4 = 6
    • next: 2 6 = 64 mod 100 = 64下一个:2 6 = 64 模 100 = 64
  • Fourth recursion: { 64 }第四次递归: { 64 }
    • return 64 mod 10 = 4 // -wrong return 64 mod 10 = 4 // -wrong

In a way, I see what's going on, but I'm not entirely sure why it's happening for this one specific case, and not for dozens of others.在某种程度上,我明白发生了什么,但我不完全确定为什么它会发生在这个特定案例中,而不是其他几十个案例中。 I admit I'm rather pushing the limits of my maths knowledge here, but I get the impression I'm just missing a tiny part of the puzzle.我承认我在这里更愿意突破我的数学知识的极限,但我得到的印象是我只是遗漏了难题的一小部分。

I reckon this post is long and arduous enough as it is.我认为这篇文章已经足够长和艰巨了。 If anyone has any insights into where I'm going wrong, I'd appreciate some pointers.如果有人对我出错的地方有任何见解,我将不胜感激。

There's a lot of problems regarding the modulo of a really big number and a lot of the sol'ns back there was basically based on basic number theory.关于一个非常大的数的模有很多问题,那里的很多求解器基本上都是基于基本的数论。 Fermat's Little Theorem, Chinese Remainder Theorem, and the Euler's Phi Function can all help you solve such problems.费马小定理、中国剩余定理、欧拉的φ函数都可以帮你解决这类问题。 I recommend you to read "A Computational Introduction to Number Theory and Algebra" by Victor Shoup.我推荐你阅读 Victor Shoup 的“数论和代数的计算介绍”。 It'll help you a lot to better simplify and approach number theory-related questions better.它将帮助您更好地简化和更好地处理与数论相关的问题。 Here's the link for the book in case you'll browse this answer.这是本书的链接,以防您浏览此答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM