动态规划 && 矩阵快速幂

来源:互联网 发布:mac移除windows分区 编辑:程序博客网 时间:2024/06/01 09:01

先看题把:


对于斐波拉契经典问题,我们都非常熟悉,通过递推公式F(n) = F(n - 1) + F(n - 2),我们可以在线性时间内求出第n项F(n),现在考虑斐波拉契的加强版,我们要求的项数n的范围为int范围内的非负整数,请设计一个高效算法,计算第n项F(n-1)。第一个斐波拉契数为F(0) = 1。

给定一个非负整数,请返回斐波拉契数列的第n项,为了防止溢出,请将结果Mod 1000000007。

测试样例:
3
返回:2

关键在于设计一个算法,可以快速的计算第n个数,我们来看递推公式,将其写成矩形相乘的形式:


接着我们就可以用快速幂了(http://blog.csdn.net/zjucor/article/details/70146583),关键在于根据递推公式写出矩阵表达式的形式

package Fabnaci;/* * 就用long[][]数组吧 * long = int * int 是没有效果的 */public class Fibonacci {    public int getNthNumber(int n) {        // write code here    long[][] a = new long[][]{    new long[]{1,1},    new long[]{1,0}    };        long[][] c = matrixPower(a, n);    return (int)c[0][0];    }            public long[][] matrixPower(long[][] a, int n) {// 注意:初始化为单位矩阵    long[][] b = new long[a.length][a.length];for(int i=0; i<a.length; i++)b[i][i] = 1;while(n != 0) {if((n & 1) != 0)b = helper(b, a);n = n >> 1;a = helper(a, a);}return b;}public long[][] helper(long[][] a, long[][] b) {long[][] c = new long[a.length][a.length];for(int i=0; i<a.length; i++)for(int j=0; j<a.length; j++)for(int k=0; k<a.length; k++) {long t = a[i][k] * b[k][j];c[i][j] += (t % 1000000007);c[i][j] %= 1000000007;}return c;}}


再看另外一个:

在农场中,奶牛家族是一个非常庞大的家族,对于家族中的母牛,从它出生那年算起,第三年便能成熟,成熟的母牛每年可以生出一只小母牛。即母牛从出生开始的第三年便能做妈妈。最开始农场只有一只母牛,它从第二年开始生小母牛。请设计一个高效算法,返回第n年的母牛总数,已知n的范围为int范围内的正整数。

给定一个正整数n,请返回第n年的母牛总数,为了防止溢出,请将结果Mod 1000000007。

测试样例:
6
返回:9
明显用DP:F(n) = F(n-1) + F(n-3),用的是3阶方阵的相乘


其实根据递推公式写矩形形式是有规律的,如下:



之前在博客http://blog.csdn.net/zjucor/article/details/70146583上写的那道题也是用这种方法,不过隐藏的比较难发现用快速幂而已

0 0
原创粉丝点击