SPOJ:Fibonacci Polynomial(矩阵递推&前缀和)

Problem description.

The Fibonacci numbers defined as f(n) = f(n-1) + f(n-2) where f0 = 0 and f1 = 1.

We define a function as follows D(n,x) = x + x^2 + 2x^3 + 3x^4 + 5x^5 + 8x^6 +...+f(n)x^n

Given two integers n and x, you need to compute D(n,x) since the output can be very large output the result modulo 1000000007 (1e9+7) .

Input

Input description.

  • The first line of the input contains an integer T denoting the number of test cases. 
    The description of T test cases follows.
  • The first line of each test case contains two integers n and x as described above.

Output

Output description.

  • For each test case, output D(n,x)%1000000007 in a seperate line.

Constraints

Should contain all the constraints on the input data that you may have. Format it like:

  • 1 ≤ T ≤ 1000
  • 0 ≤ n ≤ 10^15
  • 0 ≤ x ≤ 10^15

Example

Input:
1
7 11

Output:
268357683

题意:f(n)是斐波拉契数列,g(n)=f(n)*x^n;求前N项的g(n)的累加和。

思路:易得g(n)=g(n-1)*x+g(n-2)*x^2,

可以得到g(n)的矩阵求解方程: g(n)=base^N*g(0);  其中,base[1][1]=X; base[1][2]=X^2; base[2][1]=1(由递推式得到);

前缀和可以由大矩阵得到:A[1][1]=base; A[1][2]=1; A[2][2]=1(有前缀和求和公式得到) ;

大概地解释了一下,不是很清楚,可以看代码。前缀和可以参考这里:http://www.cnblogs.com/hua-dong/p/8479103.html

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int Mod=1e9+7;struct mat
{
    ll mp[5][5];
    mat(){memset(mp,0,sizeof(mp)); }
    mat friend operator *(mat a,mat b)
    {
        mat res;
        for(int k=1;k<=4;k++)
         for(int i=1;i<=4;i++)
          for(int j=1;j<=4;j++)
            res.mp[i][j]=(res.mp[i][j]+(a.mp[i][k]*b.mp[k][j])%Mod)%Mod;
        return res;
    }
    mat friend operator ^(mat a,ll x)
    {
        mat res;
        for(int i=1;i<=4;i++) res.mp[i][i]=1;
        while(x){
            if(x&1) res=res*a;  a=a*a;  x>>=1;
        }   return res;
    }
};
int main()
{
    ll T,N,X;
    scanf("%lld",&T);
    while(T--){
        scanf("%lld%lld",&N,&X); X%=Mod;
        mat base;
        base.mp[1][1]=X; base.mp[1][2]=X*X%Mod; base.mp[2][1]=1;
        for(int i=1;i<=2;i++) base.mp[i][i+2]=base.mp[i+2][i+2]=1;
        base=base^N;
        printf("%lld\n",base.mp[1][3]*X%Mod);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/hua-dong/p/8893887.html

时间: 2024-10-16 07:03:07

SPOJ:Fibonacci Polynomial(矩阵递推&前缀和)的相关文章

「常系数齐次线性递推」——矩阵快速幂的优化

引入: 对于递推方程: $$F(x) = \sum_{i=1}^k a_iF(x-i)$$ 我们显然会得到一个关于$F$的多项式求逆或者矩阵递推式,大多数情况下我们都是用后者,但是当$k$很大的时候,$k^3log n$的时间复杂度我们是吃不消的,那么自然我们的前人就搞出了一些优化. 特征多项式及Cayley-Hamilton定理: 一.特征多项式的定义: 设$A$是$n$阶矩阵,若数$\lambda$和非零列向量$x$使关系式$$Ax=\lambda x\;\;\;\;\;(1)$$ 成立,那

51nod1149 Pi的递推式

基准时间限制:1 秒 空间限制:131072 KB 分值: 640 F(x) = 1 (0 <= x < 4) F(x) = F(x - 1) + F(x - pi) (4 <= x) Pi = 3.1415926535..... 现在给出一个N,求F(N).由于结果巨大,只输出Mod 10^9 + 7的结果即可. Input 输入一个整数N(1 <= N <= 10^6) Output 输出F(N) Mod 10^9 + 7 Input示例 5 Output示例 3 数学问

001-算法-递推法

一.概念: 递推算法是一种简单的算法,即通过已知条件,利用特定关系得出中间推论,直至得到结果的算法.递推分为顺推和逆推两种. 递推算法使用“步步为营”的方法,不断利用已有的信息推导出新的东西. 顺推法:是指从已知条件出发,逐步推算出要解决问题的方法.例如:斐波拉契数列就可以通过顺推法不断递推算出新的数据. 逆推法:是从已知的结果出发,用迭代表达式逐步推算出问题开始的条件,即顺推法的逆过程. demo : http://blog.csdn.net/jtlyuan/article/details/7

HDU 3117 Fibonacci Numbers(Fibonacci矩阵加速递推+公式)

题目意思很简单:求第n个Fibonacci数,如果超过八位输出前四位和后四位中间输出...,否则直接输出Fibonacci数是多少. 后四位很好求,直接矩阵加速递推对10000取余的结果就是. 前四位搜了一下:http://blog.csdn.net/xieqinghuang/article/details/7789908 Fibonacci的通项公式,对,fibonacci数是有通项公式的-- f(n)=1/sqrt(5)(((1+sqrt(5))/2)^n+((1-sqrt(5))/2)^n

BZOJ 1002 + SPOJ 104 基尔霍夫矩阵 + 一个递推式。

BZOJ 1002 高精度 + 递推 f[1] = 1; f[2] = 5; f[i] = f[i - 1] * 3 - f[i - 2] + 2; SPOJ 104 裸 + 不用Mod 1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <algorithm> 5 #include <iostream> 6 7 using namespace std;

POJ3070 Fibonacci(矩阵快速幂加速递推)【模板题】

题目链接:传送门 题目大意: 求斐波那契数列第n项F(n). (F(0) = 0, F(1) = 1, 0 ≤ n ≤ 109) 思路: 用矩阵乘法加速递推. 算法竞赛进阶指南的模板: #include <iostream> #include <cstring> using namespace std; const int MOD = 10000; void mul(int f[2], int base[2][2]) { int c[2]; memset(c, 0, sizeof

openjudge1768 最大子矩阵[二维前缀和or递推|DP]

总时间限制:  1000ms 内存限制:  65536kB 描述 已知矩阵的大小定义为矩阵中所有元素的和.给定一个矩阵,你的任务是找到最大的非空(大小至少是1 * 1)子矩阵. 比如,如下4 * 4的矩阵 0 -2 -7 09 2 -6 2-4 1 -4 1-1 8 0 -2 的最大子矩阵是 9 2-4 1-1 8 这个子矩阵的大小是15. 输入 输入是一个N * N的矩阵.输入的第一行给出N (0 < N <= 100).再后面的若干行中,依次(首先从左到右给出第一行的N个整数,再从左到右给

hihoCoder 1143 : 骨牌覆盖问题&#183;一(递推,矩阵快速幂)

[题目链接]:click here~~ 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 骨牌,一种古老的玩具.今天我们要研究的是骨牌的覆盖问题: 我们有一个2xN的长条形棋盘,然后用1x2的骨牌去覆盖整个棋盘.对于这个棋盘,一共有多少种不同的覆盖方法呢? 举个例子,对于长度为1到3的棋盘,我们有下面几种覆盖方式: 提示:骨牌覆盖 提示:如何快速计算结果 输入 第1行:1个整数N.表示棋盘长度.1≤N≤100,000,000 输出 第1行:1个整数,表示覆盖方案数 M

Codeforces 446C 线段树 递推Fibonacci公式

聪哥推荐的题目 区间修改和区间查询,但是此题新颖之处就在于他的区间修改不是个定值,而是从L 到 R 分别加 F1.F2....Fr-l+1 (F为斐波那契数列) 想了一下之后,觉得用fib的前缀和来解决,每次做懒惰标记记录下当前区间是从哪个L开始加起的,敲了一半之后发现有问题,就跟上次遇到的懒惰标记问题一样,这是个覆盖性的懒惰标记,每次向下传递后,都要先清除孩子的,清除孩子的也有可能要清除son's son,所以要一直pushdown下去,否则就会错,但这样就会超时. 能不能有个累加型的标记让我