Project Euler 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?

翻译:

加和计数

将5写成整数的和有6种不同的方式:

4 + 1
3 + 2
3 + 1 + 1
2 + 2 + 1
2 + 1 + 1 + 1
1 + 1 + 1 + 1 + 1

将100写成整数的和有多少种不同的方式?

翻译来源

解题思路:

将100能够拆成整数的和能够有多少种?

1.利用动态规划求解

2.利用数的拆分求解<组合数学中有讲解>

数的拆分法

理论基础,链接中讲到了拆分的理论

P(n,k)的意思就是n拆分成k份的数量

有递推公式:

P(n,k)= P(n-1,k-1) + P(n-k,k)

初始值:

k>n时:P(n,k) = 0

对所有的n,P(n,n)=1,P(n,0)=0

也很显然的发现:

对所有的n,P(n,1)=n,P(n,2) = n/2 的向下取整

证明:P(n,k)= P(n-1,k-1) + P(n-k,k)

忘了。。。

求出所以的P(n,k)矩阵

则n的所以拆分的和是

Java程序:

//  整数n 拆分k份
    void partitions(){
        int limit = 100;
        int count = 0;
        int[][] p = new int[limit+1][limit+1];
        for(int n=0;n<=limit;n++){
            p[n][n] = 1;
            p[n][1] = 1;
            p[n][0] = 0;
        }
        for(int n=1;n<=limit;n++){
            for(int k=1;k<=n;k++){
                p[n][k] = p[n-1][k-1] + p[n-k][k];
                    if(n==limit)
                        count+=p[n][k];
                }
        }
        count = count - 1;
        System.out.println(count);
    }

结果:

//    190569291
//    running time=0s0ms

利用递归程序:

void getPar(){
        int limit = 100;
        int count = 0;
        for(int k=1;k<=limit;k++)
            count+=Par(100,k);
        count = count-1;
        System.out.println(count);
    }

    //递归形式 整数n 拆分k分
    int Par(int n,int k){
        if(k==1||n==k) return 1;
        if(k>n) return 0;
        return Par(n-1,k-1)+Par(n-k,k);
    }

结果:

//    190569291
//    running time=1s869ms

递归时间明显长了许多

动态规划求解

//动态规划求解
    void dp(){
        int limit = 100;
        int[] ways = new int[limit+1];
        ways[0] = 1 ;
        for(int i=1;i<=limit-1;i++){
            for(int j = i;j<=limit;j++)
                ways[j] += ways[j-i];
        }
        System.out.println(ways[limit]);
    }
//    190569291
//    running time=0s0ms

还看不懂

完整java程序:

package Level3;
public class PE076{

    void run(){

//        dp();
//        partitions();
//        getPar();
        int res = partitions3(100,100);
        res = res - 1;
        System.out.println(res);
    }
    int  partitions3(int n,int m ){
        if(n<=1) return 1;
        if(m>n) return partitions3(n,n);
        int sum = 0;
        for(int k=1;k<=m;k++)
            sum+=partitions3(n-k,k);
        return sum;
    }
//    190569291
//    running time=10s845ms
    void getPar(){
        int limit = 100;
        int count = 0;
        for(int k=1;k<=limit;k++)
            count+=Par(100,k);
        count = count-1;
        System.out.println(count);
    }
//    190569291
//    running time=1s869ms
    //递归形式 整数n 拆分k分
    int Par(int n,int k){
        if(k==1||n==k) return 1;
        if(k>n) return 0;
        return Par(n-1,k-1)+Par(n-k,k);
    }
    //  整数n 拆分k份
    void partitions(){
        int limit = 100;
        int count = 0;
        int[][] p = new int[limit+1][limit+1];
        for(int n=0;n<=limit;n++){
            p[n][n] = 1;
            p[n][1] = 1;
            p[n][0] = 0;
        }
        for(int n=1;n<=limit;n++){
            for(int k=1;k<=n;k++){
                p[n][k] = p[n-1][k-1] + p[n-k][k];
                    if(n==limit)
                        count+=p[n][k];
                }
        }
        count = count - 1;
        System.out.println(count);
//        for(int n=1;n<=6;n++){
//            for(int k=1;k<=n;k++)
//                System.out.print(p[n][k]+" ");
//            System.out.println();
//        }

//        for(int k=0;k<=limit;k++)
//            count+= p[limit][k];
//        count = count - 1;
//        System.out.println(count);

    }
//    190569291
//    running time=0s0ms
    //动态规划求解
    void dp(){
        int limit = 100;
        int[] ways = new int[limit+1];
        ways[0] = 1 ;
        for(int i=1;i<=limit-1;i++){
            for(int j = i;j<=limit;j++)
                ways[j] += ways[j-i];
        }
        System.out.println(ways[limit]);
    }
//    190569291
//    running time=0s0ms

    public static void main(String[] args){
        long t0 = System.currentTimeMillis();
        new PE076().run();
        long t1 = System.currentTimeMillis();
        long t = t1 - t0;
        System.out.println("running time="+t/1000+"s"+t%1000+"ms");

    }
}

Python实现

动态规划的效率很高

递归的已经不能忍了

import time 

def PE076():
    res = dp();
#     res = partitions(100,100)
    print res
def partitions(n,m):
#     limit = 100
    count = 0
    if n<=1 : return 1
    if m>n : return partitions(n,n)
    for k in range(1,m+1):
        count = count + partitions(n-k,k)
    return count
#     190569292
# running time=1073.04099989s
def dp():
    limit = 100
    ways = [0]*(limit+1)
    ways[0] = 1
    for n in range(1,limit):
        for k in range(n,limit+1):
            ways[k] +=ways[k-n]
    return ways[limit]
if __name__==‘__main__‘:
    t0 = time.time()
    PE076()
    print "running time={0}s".format((time.time()-t0))
时间: 2024-08-25 20:20:01

Project Euler 76:Counting summations的相关文章

Project Euler 77:Prime summations

原题: Prime summations It is possible to write ten as the sum of primes in exactly five different ways: 7 + 35 + 55 + 3 + 23 + 3 + 2 + 22 + 2 + 2 + 2 + 2 What is the first value which can be written as the sum of primes in over five thousand different

Project Euler 85 :Counting rectangles 数长方形

Counting rectangles By counting carefully it can be seen that a rectangular grid measuring 3 by 2 contains eighteen rectangles: Although there exists no rectangular grid that contains exactly two million rectangles, find the area of the grid with the

Python练习题 048:Project Euler 021:10000以内所有亲和数之和

本题来自 Project Euler 第21题:https://projecteuler.net/problem=21 ''' Project Euler: Problem 21: Amicable numbers Let d(n) be defined as the sum of proper divisors of n (numbers less than n which divide evenly into n). If d(a) = b and d(b) = a, where a ≠ b

Python练习题 047:Project Euler 020:阶乘结果各数字之和

本题来自 Project Euler 第20题:https://projecteuler.net/problem=20 ''' Project Euler: Problem 20: Factorial digit sum n! means n × (n ? 1) × ... × 3 × 2 × 1 For example, 10! = 10 × 9 × ... × 3 × 2 × 1 = 3628800, and the sum of the digits in the number 10! i

Python练习题 046:Project Euler 019:每月1日是星期天

本题来自 Project Euler 第19题:https://projecteuler.net/problem=19 ''' How many Sundays fell on the first of the month during the twentieth century (1 Jan 1901 to 31 Dec 2000)? Answer: 171 ''' from datetime import * firstDay = date(1901,1,1) lastDay = date(

Python练习题 035:Project Euler 007:第10001个素数

本题来自 Project Euler 第7题:https://projecteuler.net/problem=7 # Project Euler: Problem 7: 10001st prime # By listing the first six prime numbers: # 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13. # What is the 10 001st prime number? # Answer

Python练习题 034:Project Euler 006:和平方与平方和之差

本题来自 Project Euler 第6题:https://projecteuler.net/problem=6 # Project Euler: Problem 6: Sum square difference # The sum of the squares of the first ten natural numbers is, # 1**2 + 2**2 + ... + 10**2 = 385 # The square of the sum of the first ten natur

Python练习题 042:Project Euler 014:最长的考拉兹序列

本题来自 Project Euler 第14题:https://projecteuler.net/problem=14 ''' Project Euler: Problem 14: Longest Collatz sequence The following iterative sequence is defined for the set of positive integers: n → n/2 (n is even) n → 3n + 1 (n is odd) Using the rule

Python练习题 041:Project Euler 013:求和、取前10位数值

本题来自 Project Euler 第13题:https://projecteuler.net/problem=13 # Project Euler: Problem 13: Large sum # Work out the first ten digits of the sum of the following one-hundred 50-digit numbers. # Answer: 5537376230 numbers = '''371072875339021027987979982