如何在C ++中表示数字2 ^ 1000?

时间:2013-01-19 00:14:29

标签: c++

所以,如果你还没有看到,我试图在http://projecteuler.net来自Project Euler上做问题#16。它如下:

2^15 = 32768 and the sum of its digits is 3 + 2 + 7 + 6 + 8 = 26.

What is the sum of the digits of the number 2^1000?

我无法弄清楚如何在C ++中表示数字2 ^ 1000。我猜这有一个诀窍,但我真的被卡住了。我真的不想要问题的答案,我只是想知道如何将这个数字表示为一个变量,或者如果有一个技巧,也许有人可以让我知道?

6 个答案:

答案 0 :(得分:10)

将其表示为字符串。这意味着您需要编写两段代码:

  1. 您需要编写一段代码来将数字加倍,并将该数字作为字符串。

  2. 您需要编写一段代码来对表示为字符串的数字的数字求和。

  3. 有了这两件,很容易。

答案 1 :(得分:7)

一个值得了解此问题的好算法:

2^1 = 2
2^2 = 2 x 2 = 2 + 2
2^3 = 2 x (2 x 2) = (2 + 2) + (2 + 2)
2^4 = 2 x [2 x ( 2 x 2)] = [(2 + 2) + (2 + 2)] + [(2 + 2) + (2 + 2)]

因此,我们根据recursive操作计算了2的幂次addition定义:just add together two of the previous power of two.

link可以很好地解决这个问题。

答案 2 :(得分:1)

这个问题的关键在于提出一种不用实际计算2 ^ 1000的方法。

但是,如果你想要计算2 ^ 1000 - 这可能是一个好主意,因为这是测试你的其他算法是否正确的好方法 - 你会想要一些一种“bignum”库,例如gmp

mpz_t two_to_1000;
mpz_ui_pow_ui(two_to_1000, 2, 1000);

或者您可以使用C++ interfacegmp。它没有取幂,所以第一部分变得稍微复杂而不是更少,但它使得数字求和更简单:

mpz_class two_to_1000;
mpz_ui_pow_ui(two_to_1000.get_mpz_t(), 2, 1000);
mpz_class digitsum(0);
while (two_to_1000) {
    digitsum += two_to_1000 % 10;
    two_to_1000 /= 10;
}

(实际上没有理由让digitsum成为mpz,所以你可能想知道如何证明结果适合32位,将其添加为注释,并且只是使用long digitsum。)

所有这一切,我可能不会编写这个gmp代码来测试它,当整个事情是Python中的单行代码时:

 print(sum(map(int, str(2**1000))))

而且,即使将bignum转换为字符串以将每个数字转换为int来总结它们可能是解决它的最有效方法,但在我这里最慢的机器上仍然需要不到200us。并且没有理由进行复核需要与实际解决方案使用相同的语言。

答案 3 :(得分:1)

这是一个完整的程序。数字保存在矢量中。

#include <iostream>
#include <numeric>
#include <ostream>
#include <vector>

int main()
{
    std::vector<unsigned int> digits;
    digits.push_back(1);        // 2 ** 0 = 1

    const int limit = 1000;
    for (int i = 0; i != limit; ++i)
    {
        // Invariant: digits holds the individual digits of the number 2 ** i

        unsigned int carry = 0;
        for (auto iter = digits.begin(); iter != digits.end(); ++iter)
        {
            unsigned int d = *iter;
            d = 2 * d + carry;
            carry = d / 10;
            d = d % 10;
            *iter = d;
        }
        if (carry != 0)
        {
            digits.push_back(carry);
        }
    }

    unsigned int sum = std::accumulate(digits.cbegin(), digits.cend(), 0U);
    std::cout << sum << std::endl;

    return 0;
}

答案 4 :(得分:-1)

您需要1000位机器整数来表示2 ^ 1000;我从来没有听说过这样的机器。但是周围有很多大整数包,它们根据需要对所有机器字进行算术运算。最简单的解决方案可能是使用其中之一。(虽然给出了你需要的特定操作,但正如David Schwartz建议的那样对字符串进行算术可能是合适的。在一般情况下,这不是一个好主意,但是从那以后所有你正在做的是乘以2,然后取小数位数,它可能会很好。)

答案 5 :(得分:-1)

由于2 ^ 10约为10 ^ 3,并且2 ^ 1000 =(2 ^ 10)^ 100 =(10 ^ 3)^ 100 = 10 ^ 300(约)。 所以分配一个像

这样的数组
char digits[ 300 ]; // may be too few

并在每个字符中存储0到9之间的值。