Problem 16 : Power digit sum
215 = 32768 and the sum of its digits is 3 + 2 + 7 + 6 + 8 = 26.
What is the sum of the digits of the number 21000?
1. 幂的数字之和
215 = 32768, 数32768的各位数字之和为 3 + 2 + 7 + 6 + 8 = 26。
数 21000 的各位数字之和是多少?
2. 求解分析
通过问题描述可知:1)需要计算2的n次幂,把幂的各位数字相加求和, 2)2的n次幂,n会到1000,所以2n的结果可能会很大。
超大的幂肯定会超过C++数据结构支持的最大范围,所以,需要考虑使用合适的数据结构来保存一个超大的数。我们可以使用STL vector/array或者整数数组来保存最大的幂的各位数字,考虑到性能,最后使用了整数数组,如果是C++11可以使用array。另外,我们不能使用pow()来计算2的n次幂,需要重新在新的数据结构下(整数数组)计算2的n次幂。最后,把保存的几百位的幂的各位数字相加求和就可以得到结果。
Python是直接支持大整数的,所以我们不需要额外考虑数据结构,直接得到2的n次幂,然后求各位数字之和就好。
3. C++ 代码实现
按照求解分析的思路,我们定义了类PE0016。类图如下:
成员变量max_digits假设最大的幂的总的位数是400
成员变量m_digitsArray是最多有400个元素的数组,用来保存幂的各个位的值
成员函数calculatePowerOfTwo()用来计算2的n次幂
成员函数void adjustDigitsArray()用来调整超过9的位的值,如果某一位的值大于等于10,就进位
成员函数getSumOfDigits() 用来计算幂的各位的和。
成员函数getSumOfDigitsOf2Power() 通过调用函数calculatePowerOfTwo()和getSumOfDigits() 计算2的n次幂,并返回幂的各位数字之和。
C++ 代码
#include <iostream>
#include <cstring> // memset()
#include <cassert> // assert()
using namespace std;
class PE0016
{
private:
static const int max_digits = 400; // estimation
int m_digitsArray[max_digits];
void calculatePowerOfTwo(int n);
void adjustDigitsArray();
int getSumOfDigits();
public:
int getSumOfDigitsOf2Power(int n);
};
int PE0016::getSumOfDigitsOf2Power(int n)
{
calculatePowerOfTwo(n);
return getSumOfDigits();
}
void PE0016::calculatePowerOfTwo(int n)
{
memset(m_digitsArray, 0, sizeof(m_digitsArray));
m_digitsArray[0] = 1; // from left to right: unit, decade, hundred, ...
for(int i=1; i<=n; i++)
{
for (int j=0; j<max_digits; j++)
{
m_digitsArray[j] *= 2;
}
adjustDigitsArray(); // make sure every digit is not more than 9
}
}
void PE0016::adjustDigitsArray()
{
for (int j=0; j<max_digits; j++)
{
if (m_digitsArray[j] >= 10)
{
m_digitsArray[j+1] += m_digitsArray[j]/10;
m_digitsArray[j] %= 10;
}
}
}
int PE0016::getSumOfDigits()
{
int sumOfDigits = 0;
for(int i=0; i<max_digits; i++)
{
sumOfDigits += m_digitsArray[i];
}
return sumOfDigits;
}
int main()
{
PE0016 pe0016;
assert(26 == pe0016.getSumOfDigitsOf2Power(15));
cout << "The sum of the digits of the number 2^1000 is " ;
cout << pe0016.getSumOfDigitsOf2Power(1000) << "." << endl;
return 0;
}
4. Python 代码实现
正如求解分析说的,Python直接支持大整数,因此,我们可以继续使用函数pow()来计算2的n次幂。然后计算一个大整数的各位数字之和。
Python的求解方法很简洁,充分体现了Python语言的灵活和简洁。
函数getSumOfDigitsOf2Power1()分别计算了2个n次幂,然后得到幂的各位数字,最后求各位数字之和。
getSumOfDigitsOf2Power()使用一条语句就完成了所有的事情,返回2的n次幂的个位数字之和,非常紧凑,但需要认真理解sum(), map(), int(), pow()和str()各个函数。
Python 代码
import math
def getSumOfDigitsOf2Power1(n):
power = int(pow(2, n))
digits = map(int, str(power))
return sum(digits)
def getSumOfDigitsOf2Power(n):
return sum(map(int, str(int(pow(2, n)))))
def main():
assert 26 == getSumOfDigitsOf2Power(15)
print("The sum of the digits of the number (2^1000) is %d." \
% getSumOfDigitsOf2Power(1000))
if __name__ == '__main__':
main()