我意识到已经有几个主题涉及到这一点。但是我的问题不是关于如何构建这样的算法,而是要查找我在实现中犯了什么错误,从而导致数十个测试中的一个失败。
挑战:随机提供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 }
{ 123'232, 7 }
{ 28 }
8
问题:这适用于数十个测试用例(如上面的一个),但对于2个 2 101 2 ≡6.
手动:
// 6 -correct
但是,遵循以下算法:
{ 2, 2, 101, 2 }
{ 2, 2, 1 }
(我们已经可以看到结果将是4)
{ 2, 2 }
{ 64 }
4 // -wrong
从某种意义上说,我了解发生了什么,但我不确定为什么在这种特定情况下发生,而不是在其他数十种情况下发生。我承认我是在这里推销我的数学知识的极限,但是我得到的印象是我只是迷失了一小部分。
我认为这篇文章足够长而艰巨。如果有人对我要去哪里出错有任何见解,我将感谢一些提示。
答案 0 :(得分:2)
关于一个非常大的数的模有很多问题,那里的许多sol'ns基本上都是基于基本数论的。 Fermat的小定理,中国余数定理和Euler的Phi函数都可以帮助您解决此类问题。我建议您阅读Victor Shoup撰写的“数论和代数的计算导论”。它可以帮助您更好地简化和更好地解决与数论相关的问题。 Here's the link for the book in case you'll browse this answer.