矩阵快速幂 ——(递推表达式)

矩阵快速幂

首先知道矩阵

矩阵(Matrix)是一个按照长方阵列排列的复数实数集合;

矩阵乘法:

定义:设A

m×p

的矩阵,B

p×n

的矩阵,那么称

m×n

的矩阵C为矩阵AB的乘积,记作

C=A×B

,其中矩阵C中的第

i

行第

j

列元素可以表示为:

知道矩阵乘法之后,比如菲波那切数列就是一个递推式,

F(n)=F(n-1)+F(n-2); 因为矩阵乘法,所以

设 矩阵 A为

矩阵 B 为

则  A*B  则为    F(n)=        F(n-1)*1+F(n-2)*1

因为我们需要的矩阵为  A*B  的矩阵为

所以倒推到 B 矩阵 ,则 B矩阵是    ,

所以 F(n) 的矩阵为  初始矩阵   *   (B^(n-2))   n>=3;

所得到的矩阵  A[0][0]  就是F(n) 的值,时间复杂度优化的地方就是在幂指数的那部分快速幂,节约了时间。

所以关键就在于  从 递推式构造矩阵

比如:

这个构造出来的矩阵就是

自己可以写出这个矩阵,就明白了;下面给一个简单的题目,练练手。

给一个简单的练习题:   点击打开链接

#include <cstdio>
#include <cstring>
#include <cctype>
#include <cmath>
#include <set>
#include <map>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <string>
#include <bitset>
#include <vector>
#include <iostream>
#include <algorithm>
#include <stdlib.h>

using namespace std;
typedef long long LL;
const int INF=2e9+1e8;
const int MOD=1000007;
const int MAX_SIZE=1005;
const int MM=3;

LL f1,f2,a,b,c,n;

struct Mat
{
    LL maze[MM][MM];
    void set_empty()
    {
        memset(maze,0,sizeof(maze));
    }
};
Mat unit_Mat=
{
    1,0,0,
    0,1,0,
    0,0,1
};   //  定义一个单位矩阵,任何一个矩阵 乘以 单位矩阵,其值等于本身;
Mat operator *(Mat a,Mat b)  // 重载运算符  * //  定义两个矩阵的乘法,根据矩阵乘法的定义来写
{
    Mat c;
    c.set_empty();  // 一定要设置为空。清零数组;不然后面加等一个数会有垃圾值
    LL i,j,k;
    for(i=0; i<MM; i++)
    {
        for(j=0; j<MM; j++)
        {
            for(k=0; k<MM; k++)
            {
                c.maze[i][j]+=a.maze[i][k] * b.maze[k][j];
                c.maze[i][j] %= MOD;
            }
        }
    }
    return c;
}
Mat operator^(Mat a,LL N)  //  优化时间的就在此处,
//  类似与一般的int 数字的快速幂求值,思想是一样的。不懂可百度快速幂。
{
    Mat c=unit_Mat;
    while(N)
    {
        if(N&1) c=a*c;
        a=a*a;
        N>>=1;
    }
    return c;
}
void solve()
{
    Mat A,B;
    B.set_empty();
    A.set_empty();
    B.maze[0][0]=b,B.maze[1][0]=a,B.maze[2][0]=c;
    B.maze[0][1]=B.maze[2][2]=1;
    B=B^(n-2);
    A.maze[0][0]=f2,A.maze[0][1]=f1,A.maze[0][2]=1;
    LL ans=0;
    Mat C=A*B;
    printf("%lld\n",(C.maze[0][0]+MOD)%MOD);
}
int main()
{
    int times;
    scanf("%d",&times);
    while(times--)
    {
        scanf("%lld %lld %lld %lld %lld %lld",&f1,&f2,&a,&b,&c,&n);
        if(n == 1)
            printf("%lld\n",(f1+MOD)%MOD);
        else if(n == 2)
            printf("%lld\n",(f2+MOD)%MOD);
        else solve();  // 其上位特判 因为公式的定义域是  n>=3;
    }
    return 0;
}
时间: 2024-11-13 07:54:21

矩阵快速幂 ——(递推表达式)的相关文章

hdu 2842(矩阵快速幂+递推)

题意:一个中国环的游戏,规则是一个木棒上有n个环,第一个环是可以随意放上或拆下的,剩下的环x如果想放上或拆下必须前一个环x-1是放上的且前x-2个环全部是拆下的,问n个环最少多少次操作可以全部拆掉. 题解:需要进行递推,首先第一步肯定是要拆第n个环保证操作次数最少,因为后面的环是否存在对前面的环不造成影响,而先拆前面的如果要拆后面的环还是要把前面的放上,f(n)表示拆掉前n个环需要的最少操作次数,先拆第n个要拆前n-2个再拆第n个,花费f(n-2)+1,然后这时是00-0010,要拆第n-1个需

矩阵快速幂递推+欧拉降幂

题意:给出F(1) = x , F(2) = y , a , b , 和递推关系F(n) = F(i-1)*F(i-2) * ab , 求F[N]. 解法:将F(n) 转化为f(1) . f(2) 和 ab 可以知道它们的幂都是裴波纳切数列,可以通过矩阵快速幂同时根据欧拉降幂递推幂时mod1e+6. 坑点:1.注意数据范围,先膜一波. 2.快速幂函数0 的0 次方输出1 , 不撸壮或则直接特判x,y,a == 0 时为0. #include <bits/stdc++.h> #define mo

HDU 2842 Chinese Rings(矩阵快速幂+递推)

题目地址:HDU 2842 这个游戏是一个九连环的游戏. 假设当前要卸下前n个环.由于要满足前n-2个都卸下,所以要先把前n-2个卸下,需要f(n-2)次.然后把第n个卸下需要1次,然后这时候要卸下第n-1个,然后此时前n-2个都已经被卸下了.这时候把前n-2个都卸下与都装上所需的次数是一样的,因为卸下与装上的规则是一样的.所以又需要f(n-2)次,这时候前n-1个都在上面,卸下前n-1个需要f(n-1)次. 所以,总共需要2*f(n-2)+f(n-1)+1次. 然后构造如下矩阵. 1,2,1

CF821 E. Okabe and El Psy Kongroo 矩阵快速幂

LINK 题意:给出$n$条平行于x轴的线段,终点$k$坐标$(k <= 10^{18})$,现在可以在线段之间进行移动,但不能超出两条线段的y坐标所夹范围,问到达终点有几种方案. 思路:刚开始以为限制只是到达线段上就必须沿线段走,后来才发现是要求走y坐标所夹范围,那么就简单多了,很容易看出是个递推形DP,然而数据量有点大,k为10的18次,一般转移显然不可行.由于是个递推,而且y坐标最大也只有15,故使用矩阵优化递推复杂度即可. /** @Date : 2017-07-04 16:06:18

HDU 3292 【佩尔方程求解 &amp;&amp; 矩阵快速幂】

任意门:http://acm.hdu.edu.cn/showproblem.php?pid=3292 No more tricks, Mr Nanguo Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 587    Accepted Submission(s): 400 Problem Description Now Sailormoon

【66测试20161115】【树】【DP_LIS】【SPFA】【同余最短路】【递推】【矩阵快速幂】

还有3天,今天考试又崩了.状态还没有调整过来... 第一题:小L的二叉树 勤奋又善于思考的小L接触了信息学竞赛,开始的学习十分顺利.但是,小L对数据结构的掌握实在十分渣渣.所以,小L当时卡在了二叉树. 在计算机科学中,二叉树是每个结点最多有两个子结点的有序树.通常子结点被称作“左孩子”和“右孩子”.二叉树被用作二叉搜索树和二叉堆.随后他又和他人讨论起了二叉搜索树.什么是二叉搜索树呢?二叉搜索树首先是一棵二叉树.设key[p]表示结点p上的数值.对于其中的每个结点p,若其存在左孩子lch,则key

HDU 2604 Queuing (递推+矩阵快速幂)

[题目链接]:click here~~ [题目大意]: n个人排队,f表示女,m表示男,包含子串'fmf'和'fff'的序列为O队列,否则为E队列,有多少个序列为E队列. [思路]: 用f(n)表示n个人满足条件的结果,那么如果最后一个人是m的话,那么前n-1个满足条件即可,就是f(n-1): 如果最后一个是f那么这个还无法推出结果,那么往前再考虑一位:那么后三位可能是:mmf, fmf, mff, fff,其中fff和fmf不满足题意所以我们不考虑,但是如果是 mmf的话那么前n-3可以找满足

矩阵快速幂优化递推总结

RT,主要总结一下矩阵的求法. 首先能用矩阵快速幂优化的递推类型是f[n]=5f[n-3]+6f[n-2]+2f[n-1]+n^2+n+8之类的 也就是说递推是线性递推且f[n-i]前面的系数是常数,可以含有与n有关的多项式,也可以含有常数的这种递推,下面总结一下矩阵的写法: 先考虑最简单的常数,我们其实可以忽略常数,因为顶多在没有常数的矩阵外面加一行一列就行了 以f[n]=2f[n-1]+6f[n-2]+5f[n-3]+n^2+n为例 先写迭代的矩阵,一般可以写成一行,右边有几项写几项 {f[

多校第九场:贪心+矩阵快速幂中间优化+线性递推&amp;线段树递推

HDU 4968 Improving the GPA 思路:贪心的搞吧!比赛的时候想了好久,然后才发现了点规律,然后乱搞1A. 因为贪心嘛!大的情况就是刚开始每个人的分数都是最大的最小值,即绩点4.0的最低分数85,然后最后一个数设为剩余的分数,然后如果小于60就从第一个分数补到这个分数来,然后最后一个分数还小于60,那就用第二个补--依次往下搞,那时我也不知道这样就搞出答案了,我还没证明这个对不对呢,哈哈. 小的情况:小的情况就是先假设每个人都是绩点最小的最大分数,即绩点2.0的最大分数69,