• Project Euler 101 :Optimum polynomial 最优多项式


    Optimum polynomial

    If we are presented with the first k terms of a sequence it is impossible to say with certainty the value of the next term, as there are infinitely many polynomial functions that can model the sequence.

    As an example, let us consider the sequence of cube numbers. This is defined by the generating function,
    un = n3: 1, 8, 27, 64, 125, 216, …

    Suppose we were only given the first two terms of this sequence. Working on the principle that “simple is best” we should assume a linear relationship and predict the next term to be 15 (common difference 7). Even if we were presented with the first three terms, by the same principle of simplicity, a quadratic relationship should be assumed.

    We shall define OP(k, n) to be the nth term of the optimum polynomial generating function for the first k terms of a sequence. It should be clear that OP(k, n) will accurately generate the terms of the sequence for n ≤ k, and potentially the first incorrect term (FIT) will be OP(k, k+1); in which case we shall call it a bad OP(BOP).

    As a basis, if we were only given the first term of sequence, it would be most sensible to assume constancy; that is, for n ≥ 2, OP(1, n) = u1.

    Hence we obtain the following OPs for the cubic sequence:

      
    OP(1, n) = 1 1, 1, 1, 1, …
    OP(2, n) = 7n−6 1, 8, 15, …
    OP(3, n) = 6n2−11n+6 1, 8, 27, 58, …
    OP(4, n) = n3 1, 8, 27, 64, 125, …

    Clearly no BOPs exist for k ≥ 4.

    By considering the sum of FITs generated by the BOPs (indicated in red above), we obtain 1 + 15 + 58 = 74.

    Consider the following tenth degree polynomial generating function:

    un = 1 − n + n2 − n3 + n4 − n5 + n6 − n7 + n8 − n9 + n10

    Find the sum of FITs for the BOPs.


    最优多项式

    如果我们知道了一个数列的前k项,我们仍无法确定地给出下一项的值,因为有无穷个多项式生成函数都有可能是这个数列的模型。

    例如,让我们考虑立方数的序列,它可以用如下函数生成,
    un = n3: 1, 8, 27, 64, 125, 216, …

    如果我们只知道数列的前两项,秉承“简单至上”的原则,我们应当假定这个数列遵循线性关系,并且预测下一项为15(公差为7)。即使我们知道了数列的前三项,根据同样的原则,我们也应当首先假定数列遵循二次函数关系。

    给定数列的前k项,定义OP(k, n)是由最优多项式生成函数给出的第n项的值。显然OP(k, n)可以精确地给出n ≤ k的那些项,而可能的第一个不正确项(First Incorrect Term,简记为FIT)将会是OP(k, k+1);如果事实的确如此,我们称这个多项式为坏最优多项式(Bad OP,简记为BOP)。

    在最基本的情况下,如果我们只得到了数列的第一项,我们应当假定数列为常数,也就是说,对于n ≥ 2,OP(1, n) = u1。

    由此,我们得到了立方数列的最优多项式如下:

      
    OP(1, n) = 1 1, 1, 1, 1, …
    OP(2, n) = 7n−6 1, 8, 15, …
    OP(3, n) = 6n2−11n+6 1, 8, 27, 58, …
    OP(4, n) = n3 1, 8, 27, 64, 125, …

    显然,当k ≥ 4时不存在坏最优多项式。

    所有坏最优多项式的第一个不正确项(用红色标示的数)之和为1 + 15 + 58 = 74。

    考虑下面这个十阶多项式生成函数:

    un = 1 − n + n2 − n3 + n4 − n5 + n6 − n7 + n8 − n9 + n10

    求其所有坏最优多项式的第一个不正确项之和。

    解题

    mathblog 提到拉格朗日多项式,突然明白了。

    wiki中拉格朗日多项式的定义,在数值计算方法中叫拉格朗日差值函数

    上面第k+1项就是所求的答案,至于为什么?已知的点很显然能够准确的预测出来,对于未知的点,为什么第k+1个点不能够预测对?

    根据上面博客中写的程序,我记忆中本科时候好像写过这个程序的。

    Java

    package Level4;
    
    
    public class PE0101{
        public static void run(){
            Lagrange();
            
        }
        public static void Lagrange(){
            long[] coef = {1,-1,1,-1,1,-1,1,-1,1,-1,1};
            Polynomial poly = new Polynomial(coef);
            
            long[] y = new long[coef.length];
            for(int i=0;i<y.length;i++)
                y[i] = poly.evaluate(i+1);
            
            long fits = 0;
            for(int n=1;n<=coef.length -1;n++){
                long result = 0;
                for(int i =1;i<=n;i++){
                    long tmp1 = 1;
                    long tmp2 = 1;
                    for(int j=1;j<=n;j++){
                        if(i==j)
                            continue;
                        else{
                            tmp1 *= n + 1-j;
                            tmp2 *= i-j;
                        }
                    }
                    result +=tmp1*y[i-1]/tmp2;
                }
                fits +=result;
            }
            System.out.println(fits);
        }
    
        public static void main(String[] args){
            long t0 = System.currentTimeMillis();
            run();
            long t1 = System.currentTimeMillis();
            long t = t1 - t0;
            System.out.println("running time="+t/1000+"s"+t%1000+"ms");
    //        37076114526
    //        running time=0s1ms
        }
    }
    class Polynomial{
        private long[] coef;
        public int Degree;
        public Polynomial(int deg){
            Degree = deg;
            coef = new long[deg+1];
        }
        public Polynomial(long[] coef){
            Degree = coef.length - 1;
            this.coef = coef;
        }
        public long get(int i){
            return coef[i];
        }
        public void set(int i,long value){
            coef[i] = value;
        }
        public long evaluate(long x){
            long result =0;
            for(int i= this.Degree;i>=0;i--){
                result = result *x +get(i);
            }
            return result;
        }
        
    }

    Python

    # coding=gbk
    
    import time as time 
    import re 
    import math
    
    def run():
        y = ploy()
        fits = 0 
        for n in range(1,11):
            res = 0
            for i in range(1,n+1):
                tmp1 = 1
                tmp2 = 1
                for j in range(1,n+1):
                    if i==j:
                        continue
                    else:
                        tmp1 *= (n+1-j)
                        tmp2 *= (i-j)
                res += tmp1*y[i-1]/tmp2
            fits += res 
        print res  
    def ploy():
        coef = [1,-1,1,-1,1,-1,1,-1,1,-1,1]
        y = list()
        
        for n in range(1,11):
            res = 1
            m = n 
            for i in range(1,11):
                res = res + coef[i] * m
                m *=n 
            y.append(res)
        print y 
        return y 
            
        
    t0 = time.time()
    run() 
    t1 = time.time()
    print "running time=",(t1-t0),"s"
    
    
                
  • 相关阅读:
    【转】Linux 查看CPU信息、机器型号等硬件信息
    荐书
    软件架构的5种视图
    MariaDB 10.4.12 Stable Row size too large (> 8126). Changing some columns to TEXT or BLOB may help. 亲测有效
    配置MariaDB允许远程连接的方法
    MariaDB 10.4.12 Stable 绿色版下载安装
    最完整的Markdown基础教程
    Java开发环境配置 JDK开发环境配置
    centos7 断电导致 generating /run/initramfs/rdsosreport.txt 问题
    高性能分布式锁-redisson
  • 原文地址:https://www.cnblogs.com/bbbblog/p/5137805.html
Copyright © 2020-2023  润新知