Tribonacci数列前n项和的求解问题

来源:互联网 发布:linux 关闭进程脚本 编辑:程序博客网 时间:2024/05/21 09:31

2016年西电网络赛原题
Tribonacci数列是斐波那挈数列的扩展

Tribonacci数列
很有趣的,我们可以发现
这里写图片描述

这是Tribonacci数列的一些深入研究
下面是贴代码的时间了:
解法一(半产品)
这种方法就不解释了,不懂就去看看最笨的方法递归求解,而这是对递归求解的优化

import java.util.Scanner;public class Main {    public static void main(String[] args) {        Scanner scanner = new Scanner(System.in);        while (scanner.hasNext()) {            long l = scanner.nextLong();            long r = scanner.nextLong();            long sum = 0;             sum = sum_tribonacci(l, r);             System.out.println(sum % 1000000007);//          for (long i = 0; i <= 100l; i++) {//              sum = sum_tribonacci(0, i);//              System.out.println(i + "---------------------------" + sum//                      % 1000000007l);//          }        }    }    public static long sum_tribonacci(long l, long r) {        long n1 = 0, n2 = 0, n3 = 0;        long u1, u2;        long sum = 0;        if (r < 3) {            return (r - l + 1);        }        n1 = 0;        n2 = 1;        n3 = 2;        // n1 = 1;        // n2 = 1;        // n3 = 1;        long n4 = 0;        if (l < 3) {            // for (long i = 3; i <= r; i++) {            for (long i = 3; i <= r + 1; i++) {                n4 = n3 + n2 + n1;                n1 = n2;                n2 = n3;                n3 = n4;            }            sum = n3 - l;            return sum;        } else {            // for (long i = 3; i <= l; i++) {            for (long i = 3; i <= l; i++) {                n4 = n3 + n2 + n1;                n1 = n2;                n2 = n3;                n3 = n4;            }            long sum1 = n3;            // sum+=n4;            for (long i = l + 1; i <= r + 1; i++) {                n4 = n3 + n2 + n1;                n1 = n2;                n2 = n3;                n3 = n4;            }            long sum2 = n3;            return sum2 - sum1;        }    }}

解法二
这里写图片描述
所以这里关键是要求出矩阵A
可以用前5项求出矩阵(数列{1、2、3、6、11…}依题意这是数列{1、1、1、3、5…}前n-1项的和,依然满足Tribonacci规则)
这里矩阵的n次幂,我采用的是二分法。

import java.math.BigDecimal;import java.util.Scanner;public class CopyOfMain2 {    public static BigDecimal i1000000007 = new BigDecimal(            String.valueOf(1000000007));    //这里定义了四个数,其实是为了下面BigDecimal数组的初始化做准备    public static BigDecimal i3 = new BigDecimal(String.valueOf(3));    public static BigDecimal i2 = new BigDecimal(String.valueOf(2));    public static BigDecimal i1 = new BigDecimal(String.valueOf(1));    public static BigDecimal i0 = new BigDecimal(String.valueOf(0));    public static void main(String[] args) {        Scanner scanner = new Scanner(System.in);        while (scanner.hasNext()) {            long l = scanner.nextLong();            long r = scanner.nextLong();            BigDecimal[] sum = {i0,i0};            sum = Tribonacci(l, r).divideAndRemainder(i1000000007);            if(sum[1].longValue()<0)System.out.println(sum[1].add(i1000000007));            else System.out.println(sum[1]);            //这是比较笨的方法,用这种遍历的求和方式当然会超时            // for (long i = l; i <= r; i++) {            //    sum += Tribonacci(i);            // }            // for(long i =0; i <= 100l; i++){            //    sum=Tribonacci(0,i);            //    System.out.println(i+"---------------------------"+sum %            //    1000000007l);            // }        }    }    public static BigDecimal Tribonacci(long l, long r) {        BigDecimal sum = i0;        if (r < 3) {            for (long i = l; i <= r; i++) {                sum = new BigDecimal(String.valueOf(r - l + 1));            }            return sum;        }        BigDecimal[][] base = { { i1, i1, i0 }, { i1, i0, i1 }, { i1, i0, i0 } };        if (l >= 3l) {            BigDecimal[][] res1 = matrixPower(base, l - 3);            BigDecimal[][] res = matrixPower(base, r - 2);            // long[][] res = muliMatrix(res1,matrixPower(base, r- l+1));            return (res[0][0].subtract(res1[0][0])).multiply(i3)                    .add((res[1][0].subtract(res1[1][0])).multiply(i2))                    .add((res[2][0].subtract(res1[2][0])));        } else {            BigDecimal[][] res = matrixPower(base, r - 2);            return (res[0][0].multiply(i3).add(res[1][0].multiply(i2))                    .add(res[2][0]).subtract(new BigDecimal(String.valueOf(l))));        }    }    //求Tribonacci数列每一项的方法    // public static long Tribonacci(long n) {    // if (n == 0l || n == 1l || n == 2l) {    // return 1;    // } else if (n == 3l)    // return 3;    // long[][] base = { { 1l, 1l, 0l}, { 1l, 0l, 1l }, { 1l, 0l, 0l } };    // long sum = 0l;    //    // long[][] res = matrixPower(base, n - 3l);    //    // return 3l * res[0][0] + res[1][0] + res[2][0];    // }    public static BigDecimal[][] matrixPower(BigDecimal[][] base, long p) {        BigDecimal[][] res = new BigDecimal[base.length][base[0].length];        for (int i = 0; i < res.length; i++) {            for (int j = 0; j< res[0].length; j++) {                if (i == j) {                    res[i][j] = i1;                } else                    res[i][j] = i0;            }        }        BigDecimal tmp[][] = base;        for (; p != 0; p >>= 1) {            if ((p & 1) != 0) {                res = muliMatrix(res, tmp);            }            tmp = muliMatrix(tmp, tmp);        }        return res;    }    private static BigDecimal[][] muliMatrix(BigDecimal[][] m1,            BigDecimal[][] m2) {        BigDecimal[][] res = new BigDecimal[m1.length][m2[0].length];        for (int i = 0; i < res.length; i++) {            for (int j = 0; j< res[0].length; j++) {                res[i][j] = i0;            }        }        for (int i = 0; i < m1.length; i++) {            for (int j = 0; j < m2[0].length; j++) {                for (int k = 0; k < m2.length; k++) {                        res[i][j] = res[i][j].add(m1[i][k].multiply(m2[k][j])).divideAndRemainder(i1000000007)[1];                }            }        }        return res;    }}

转载请注明网址来源

3 0
原创粉丝点击