Problem 76 : Counting summations
It is possible to write five as a sum in exactly six different ways:
4 + 1
3 + 2
3 + 1 + 1
2 + 2 + 1
2 + 1 + 1 + 1
1 + 1 + 1 + 1 + 1
How many different ways can one hundred be written as a sum of at least two positive integers?
1. 欧拉项目第76道题 计数求和
可以用6种不同的方式把5写成一个和。
4 + 1
3 + 2
3 + 1 + 1
2 + 2 + 1
2 + 1 + 1 + 1
1 + 1 + 1 + 1 + 1
有多少种方法可以把100写成至少两个正整数的和呢?
2. 求解分析
下面两个问题跟本题相似或相同:
Problem 31 : Coin sums
1077. 自然数的拆分问题
我们发现 Generating function 或者 母函数可以用来解决这道题。可以点击链接看详细的说明。
3. C++ 代码实现
C++ 代码
#include <iostream>
#include <cassert>
#include <ctime>
using namespace std;
class PE0076
{
private:
static const int max_num = 400;
public:
long long countingSummations(int max_num);
};
long long PE0076::countingSummations(int num)
{
long long mul_array[max_num+1] = { 0 };
long long tmp_array[max_num+1] = { 0 };
int fact_array[max_num+1];
assert(num <= max_num);
mul_array[0] = 1;
for (int k = 0; k <= num; k++)
{
fact_array[k] = k + 1;
}
for (int i = 0; i <= num - 2; i++)
{
memset(tmp_array, 0, sizeof(tmp_array)); // initialize tmp_array[]
for (int j = 0; j <= num; j += fact_array[i]) // j power
{
for (int k = 0; k + j <= num; k++) // k power
{
tmp_array[k + j] += mul_array[k];
}
}
copy(tmp_array, tmp_array+num+1, mul_array); // copy tmp_array[] to mul_array[]
}
return mul_array[num];
}
int main()
{
clock_t start = clock();
PE0076 pe0076;
assert(6 == pe0076.countingSummations(5));
int n = 100;
cout << "Number " << n << " can be written " << pe0076.countingSummations(n);
cout << " different " << endl;
cout << "ways as a sum of at least two positive integers." << endl;
clock_t finish = clock();
double duration = (double)(finish - start) / CLOCKS_PER_SEC;
cout << "C/C++ running time: " << duration << " seconds" << endl;
return 0;
}
4. Python 代码实现
Python采用了跟C++一样的方法,使用生成函数或母函数来求解本题。
值得说明的是,C++由于有数据结构限制(直接支持的正整数最大的类型是long long), 因此最大的数小于500,但Python内置支持大整数的,所以,最大的数可以远超500。
Python代码
import time
def countingSummations(num):
mul_list, tmp_list = [0]*(num+1), [0]*(num+1)
fact_list = [ k+1 for k in range(num+1) ]
mul_list[0] = 1
for i in range(num-1):
for k in range(num+1):
tmp_list[k] = 0 # initialize array tmp_list[]
j = 0
while j <= num: # j power
for k in range(num-j+1): # k power
tmp_list[k+j] += mul_list[k]
j += fact_list[i]
for k in range(num+1):
mul_list[k] = tmp_list[k] # copy tmp_list[] to mul_list[]
return mul_list[num]
def main():
start = time.process_time()
assert(6 == countingSummations(5));
n = 100
print("Number %d can be written %d different"%(n, countingSummations(n)))
print("ways as a sum of at least two positive integers.")
end = time.process_time()
print('CPU processing time : %.5f' %(end-start))
if __name__ == '__main__':
main()