Project Euler Problem 76 (C++和Python代码实现和解析)

本文探讨了欧拉项目第76题的求解,即计算100可以由多少种不同方式写成至少两个正整数的和。通过分析,介绍了生成函数或母函数的使用,并提供了C++和Python的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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()
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值