矩阵与数列优化

心怀滕王高阁,手握物理周测······心绪阑干。校服不耐五更寒。

请看这样一道小题:原题地址https://www.luogu.org/problemnew/show/P1939;

题目描述

a[1]=a[2]=a[3]=1

a[x]=a[x-3]+a[x-1] (x>3)

求a数列的第n项对1000000007(10^9+7)取余的值。

其中n高达2*10^9。

于是暴力挂了,只能另寻它道。

这时,学习后几乎从未使用过的技能矩阵乘法终于亮出了刀锋。

矩阵乘法与递推数列的求和有何关系?

针对此题,我们可以视数列为1x3矩阵{a[x-3],a[x-2],a[x-1]},由此矩阵乘以某个矩阵后得到新的1x3矩阵{a[x-2],a[x-1],a[x]}。

又因为a[x]=a[x-1]+a[x-3],利用矩阵乘法性质,构造出了3x3矩阵

0 0 1

1 0 0

0 1 1

直接利用矩阵快速幂

设原矩阵为a,构造矩阵为b,所求矩阵为c,则k>=3时,有c=a*(b^(k-3));

以此,得以AC。

不过输出时一定记得取模!!!我就这样挂掉了第一遍,只得十分。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#define ll long long
using namespace std;
const ll modd=1e9+7;
ll n,k,T;
struct zz
{
    ll x[4][4];
    int n,m;
    zz operator * (zz b) const
    {
        zz mid;
        mid.n=n;
        mid.m=b.m;
        memset(mid.x,0,sizeof(mid.x));
        for(int i=1;i<=mid.n;i++)
            for(int j=1;j<=mid.m;j++)
                for(int k=1;k<=m;k++)
                    mid.x[i][j]=mid.x[i][j]%modd+x[i][k]*b.x[k][j]%modd;
        return mid;
    }
}dw;
zz ksm(zz a,ll k)
{
    zz c;c.n=3;c.m=3;
    memset(c.x,0,sizeof(c.x));
    c.x[1][1]=c.x[2][2]=c.x[3][3]=1;
    while(k)
    {
        if(k&1)c=c*a;
        a=a*a;
        k>>=1;
    }
    return c;
}
int main()
{
    scanf("%lld",&T);
    zz s,t;
    s.n=s.m=3;dw.n=1;dw.m=3;
    s.x[1][1]=0;s.x[1][2]=0;s.x[1][3]=1;
    s.x[2][1]=1;s.x[2][2]=0;s.x[2][3]=0;
    s.x[3][1]=0;s.x[3][2]=1;s.x[3][3]=1;
    dw.x[1][1]=dw.x[1][2]=dw.x[1][3]=1;
    while(T--)
    {
        scanf("%lld",&k);
        if(k<=3){printf("1\n");continue;}
        t=ksm(s,k-3);
        t=dw*t;
        printf("%lld\n",t.x[1][3]%modd);
    }
    return 0;
}

同样滴,对于斐波那契数列,矩阵乘法同样是相当适用。

F(0)=1 , F(1)=1 , F(n)=F(n-1)+F(n-2)

矩阵变为2x2

0 1

1 1

对于像洛谷1306这种题,最后一组数据甚至卡爆了大部分题解,唯有矩乘方能刷过(打表这种面向数据编程的方法不算)

总结一句,对于递推数列求项数,矩乘实在是不二之选,构造也十分轻松。

原文地址:https://www.cnblogs.com/czktransformers/p/9689631.html

时间: 2024-10-19 02:05:35

矩阵与数列优化的相关文章

矩阵快速幂优化递推总结

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[

poj 3744 概率dp 矩阵快速幂优化

一位童子兵要穿过一条路,路上有些地方放着地雷.这位童子兵非常好玩,走路一蹦一跳的.每次他在 i 位置有 p 的概率走一步到 i+1 ,或者 (1-p) 的概率跳一步到 i+2.童子兵初始在1位置,求他安全通过这条道路的概率. 以所在位置为状态,dp[i] 表示在位置 i 的安全的概率. dp[i] = p * dp[i-1] + (1 - p) * dp[i-2]; // i 位置没有地雷 但是题目数据的范围是 10^8 这样dp的话会 TLE. 想想可以用矩阵快速幂优化.简单退出矩阵是 |p

HDU 5863 cjj&#39;s string game ( 16年多校10 G 题、矩阵快速幂优化线性递推DP )

题目链接 题意 : 有种不同的字符,每种字符有无限个,要求用这k种字符构造两个长度为n的字符串a和b,使得a串和b串的最长公共部分长度恰为m,问方案数 分析 : 直觉是DP 不过当时看到 n 很大.但是 m 很小的时候 发现此题DP并不合适.于是想可能是某种组合数学的问题可以直接公式算 看到题解的我.恍然大悟.对于这种数据.可以考虑一下矩阵快速幂优化的DP 首先要想到线性递推的 DP 式子 最直观的想法就是 dp[i][j] = 到第 i 个位置为止.前面最长匹配长度为 j 的方案数 但是如果仔

矩阵快速幂优化线性递推

我们熟知的斐波那契数列递推公式是: \(f(n)=f(n-1)+f(n-2)\) 假设我们需要求斐波那契数列的第n项,当n非常大(如n=1e9)的时候,递推肯定超时.我们不妨设: \(\binom{f_{n}}{f_{n-1}}=\begin{pmatrix}a & b\\ c & d\end{pmatrix}\binom{f_{n-1}}{f_{n-2}}\) 将等式右边乘开,得到: \(\binom{af_{n-1}+bf_{n-2}}{cf_{n-1}+df_{n-2}}\) 要使其

[题解][SHOI2013]超级跳马 动态规划/递推式/矩阵快速幂优化

这道题... 让我见识了纪中的强大 这道题是来纪中第二天(7.2)做的,这么晚写题解是因为 我去学矩阵乘法啦啦啦啦啦对矩阵乘法一窍不通的童鞋戳链接啦 层层递推会TLE,正解矩阵快速幂 首先题意就是给你一个 n 行m 列 的格子图 一只马从棋盘的左上角跳到右下角.每一步它向右跳奇数列,且跳到本行或相邻行. 题意很简单暴力dp的思路也很简单但是数据很恶心虽然远古一点,但毕竟是省选题 1 ≤ n ≤ 50,2 ≤ m ≤ 10^9 不过还是给了我们一点提示:n这么小? 总之我们先找出转移式对于每一个点

HDU2604-- Queuing(矩阵快速幂优化)

Queuing Time Limit:5000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Description Queues and Priority Queues are data structures which are known to most computer scientists. The Queue occurs often in our daily life. There

hdoj 4062 Queuing 【矩阵快速幂优化递推公式】

Queuing Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3609    Accepted Submission(s): 1629 Problem Description Queues and Priority Queues are data structures which are known to most computer

POJ3744——概率DP 矩阵快速幂优化——Scout YYF I

http://poj.org/problem?id=3744 矩阵快速幂: 利用DP的递推式 就本题来说 dp[i] = p*dp[i-1] + (1-p)*dp[i-2] 由于x非常大最大1亿,这样的话复杂度就为1亿 所以这里可以用矩阵的思想 [dp[i]   dp[i-1] ] = [ dp[i-1]  dp[i-2] ] | p   1 - p| | 1      0  | 递推得到 n - 1 [dp[n]   dp[n-1]] = [dp[1]   dp[2] ] |p   1 - p

hdu 5564 Clarke and digits 矩阵快速幂优化数位dp

Clarke and digits Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Problem Description Clarke is a patient with multiple personality disorder. One day, Clarke turned into a researcher, did a research on digits. He w