P1939 【模板】矩阵加速(数列)

链接:P1939 【模板】矩阵加速(数列)

题目描述

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

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

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

输入输出格式

输入格式:
第一行一个整数T,表示询问个数。

以下T行,每行一个正整数n。

输出格式:
每行输出一个非负整数表示答案。

输入输出样例

输入样例#1:
3
6
8
10
输出样例#1:
4
9
19
说明

对于30%的数据 n<=100;

对于60%的数据 n<=2*10^7;

对于100%的数据 T<=100,n<=2*10^9;

题干

#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<algorithm>
#include<math.h>
#include<cstring>
using namespace std;
#define LL unsigned long long
#define MOD 1000000007
struct node{
    LL v[3][3];
}x,b,ans,p;
LL T,n;
node cheng(node x,node y)
{
    for(int i=0;i<=2;i++)
    for(int j=0;j<=2;j++)
    {
        p.v[i][j]=0;
        for(int k=0;k<=2;k++)
        p.v[i][j]=(p.v[i][j]+x.v[i][k]*y.v[k][j])%MOD;
    }
    return p;
}
void fastlow()
{
    while(n)
    {
        if(n%2)    ans=cheng(ans,x);
        x=cheng(x,x);n/=2;
    }
}

int main()
{
    scanf("%lld",&T);
    b.v[0][1]=b.v[0][2]=b.v[0][0]=1;
    x.v[0][0]=x.v[0][1]=1;
    x.v[1][2]=1;
    x.v[2][0]=1;
    ans=cheng(b,x);
    for(int i=1;i<=T;i++)
    {
        scanf("%lld",&n);

        x.v[0][0]=x.v[0][1]=1;x.v[0][2]=0;
        x.v[1][2]=1;x.v[1][0]=x.v[1][1]=0;
        x.v[2][0]=1;x.v[2][1]=x.v[2][2]=0;
        ans=cheng(b,x);
        if(n<=3)
        {
            printf("1\n");
            continue;
        }
        n-=4;fastlow();
        printf("%lld\n",ans.v[0][0]);
    }
    return 0;
}

代码

要注意的问题:

  因为有T组数据,所以要初始化“乘数单元“(0,1都要初始化!)。

  记得要调用函数名,只写括号是不对但能编译过的。这个错误最难找。
  

时间: 2024-12-14 18:42:24

P1939 【模板】矩阵加速(数列)的相关文章

[LGOJ]P1939【模板】矩阵加速(数列)[矩阵加速递推]

题面 矩阵加速递推的原理: 首先你得会矩阵乘法与快速幂. 以斐波拉契数列为例, 要从矩阵A \[ \begin{bmatrix} f[n-1] & f[n]  \end{bmatrix} \] 得到矩阵B \[ \begin{bmatrix} f[n] & f[n+1]  \end{bmatrix} \] 显然可以\[\begin{bmatrix} f[n-1] & f[n] \end{bmatrix}\times \begin{bmatrix}  0 & 1\\ 1 &a

【luogu P1939 【模板】矩阵加速(数列)】 题解

题目链接:https://www.luogu.org/problemnew/show/P1939 对于矩阵推序列的式子: 由题意知: f[x+1] =1f[x] + 0f[x-1] + 1f[x-2] f[x] = 1f[x] + 0f[x-1] + 0f[x-2] f[x-1] = 0f[x] + 1f[x-1] + 0*f[x-2] 所以矩阵初项的系数: 1 1 0 0 0 1 1 0 0 #include <cstdio> #include <cstring> #includ

斐波那契数列F(n)【n超大时的(矩阵加速运算) 模板】

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

【矩阵加速】 矩阵 快速幂

矩阵的快速幂是用来高效地计算矩阵的高次方的.将朴素的o(n)的时间复杂度,降到log(n). 这里先对原理(主要运用了矩阵乘法的结合律)做下简单形象的介绍: 一般一个矩阵的n次方,我们会通过连乘n-1次来得到它的n次幂. 但做下简单的改进就能减少连乘的次数,方法如下: 把n个矩阵进行两两分组,比如:A*A*A*A*A*A => (A*A)*(A*A)*(A*A) 这样变的好处是,你只需要计算一次A*A,然后将结果(A*A)连乘自己两次就能得到A^6,即(A*A)^3=A^6.算一下发现这次一共乘

算法学习笔记 递归之 快速幂、斐波那契矩阵加速

递归的定义 原文地址为:http://blog.csdn.net/thisinnocence 递归和迭代是编程中最为常用的基本技巧,而且递归常常比迭代更为简洁和强大.它的定义就是:直接或间接调用自身.经典问题有:幂运算.阶乘.组合数.斐波那契数列.汉诺塔等.其算法思想: 原问题可分解子问题(必要条件): 原与分解后的子问题相似(递归方程): 分解次数有限(子问题有穷): 最终问题可直接解决(递归边界): 对于递归的应用与优化,直接递归时要预估时空复杂度,以免出现用时过长或者栈溢出.优化递归就是以

【HDU3802】【降幂大法+矩阵加速+特征方程】Ipad,IPhone

Problem Description In ACM_DIY, there is one master called “Lost”. As we know he is a “-2Dai”, which means he has a lot of money.  Well, Lost use Ipad and IPhone to reward the ones who solve the following problem.  In this problem, we define F( n ) a

递推&#183;矩阵加速

这个题其实很简单,简单分析一下规律,发现发f[i]=f[i-1]+f[i-2]. 如下图: 程序: 1 #include<iostream> 2 using namespace std; 3 int main() 4 { 5 int n,i,j,a[101]; 6 cin>>n; 7 a[1]=1;a[2]=2; 8 for (i=3;i<=n;i++) 9 { 10 a[i]=a[i-1]+a[i-2]; 11 } 12 cout<<a[n]; 13 } 用这个

矩阵经典题目七:Warcraft III 守望者的烦恼(矩阵加速递推)

https://www.vijos.org/p/1067 很容易推出递推式f[n] = f[n-1]+f[n-2]+......+f[n-k]. 构造矩阵的方法:构造一个k*k的矩阵,其中右上角的(k-1)*(k-1)的矩阵是单位矩阵,第k行的每个数分别对应f[n-1],f[n-2],,f[n-k]的系数.然后构造一个k*1的矩阵,它的第i行代表f[i],是经过直接递推得到的.设ans[][]是第一个矩阵的n-k次幂乘上第二个矩阵,f[n]就是ans[k][1]. 注意:用__int64 #in

HDU 5564 Clarke and digits 状压dp+矩阵加速

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5564 题意: 求长度在[L,R]范围,并且能整除7的整数的总数. 题解: 考虑最原始的想法: dp[i][j][k]表示长度为i,并且对7取模得到j的以k结尾的数. 则有状态转移方程dp[i+1][(h*10)+l)%7][k]+=dp[i][h][k'](k+k'!=K). 但是i范围是1~10^9,需要矩阵加速. 这里对dp[i][j][k]的[j][k]两个状态进行压缩,得到转移矩阵mat[