模板C++ 02数论算法 4矩阵乘法

矩阵乘法:用来求某种 递推关系。

矩阵相乘只有在第一个矩阵的列数和第二个矩阵的行数相同时才有意义

定义

A为A*M的矩阵,B为M*B的矩阵,那么矩阵C为矩阵AB的乘积,其中矩阵C中的第i行第j列元素可以表示为:

如下所示:

开一个2*2的矩阵:主要是为了快速幂的方便,一个可以和自己乘上许多次(>=2)的矩阵只有可能是正方形的,所以要开这样一个矩阵。

【题目描述】

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。

【输出格式】

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

【样例输入】3 6 8 10

【样例输出】4 9 19

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

然后就是使用矩阵乘法来递推。

如果想要预处理,也是可以的,只不过T<=100,所以偷懒省空间。

struct mod
{
    long long a[4][4];
    mod() { memset(a,0,sizeof(a)); }
};
mod mul(mod a,mod b)//矩阵乘法
{
    mod c;
    for(int i=1;i<=3;i++)
        for(int j=1;j<=3;j++)
            for(int k=1;k<=3;k++)
                c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j])%1000000007;
    return c;
}
void make(int n)
{
    mod a,c;
    c.a[1][1]=1;c.a[2][1]=1;c.a[3][1]=1;
    a.a[1][1]=0;a.a[1][2]=1;a.a[1][3]=0;
    a.a[2][1]=0;a.a[2][2]=0;a.a[2][3]=1;
    a.a[3][1]=1;a.a[3][2]=0;a.a[3][3]=1;
    n++;
    while(n>0)//快速幂
    {
        if(n&1) c=mul(c,a);//不能是mul(a,c)
        a=mul(a,a);//(A^n)*B
        n>>=1;
    }
    printf("%d\n",c.a[3][3]%1000000007);
}
int main(int argc,char *argv[])
{
    int t;scanf("%d",&t);
    while(t--)
    {
        int n;
        scanf("%d",&n);
        make(n);
    }
}
时间: 2024-08-27 12:21:05

模板C++ 02数论算法 4矩阵乘法的相关文章

模板C++ 02数论算法 1最大公约数 AND 2素数判断

2.1最大公约数Greatest Common Divisor 补充知识:x*y=最小公倍数*最大公约数 int Euclid(int a,int b) { if(b==0) return a; return Euclid(b,a%b); } 2.2素数判断Prime #include<cmath> bool Prime(int n) { int t=sqrt(n); for(int i=2;i<=t;i++) if(n%i==0) return false; return true;

模板C++ 02数论算法 5快速幂及快速乘

2.5快速幂及快速乘 int qmul(int x,int y) { int s=0; while(y) { if(y&1) s=(s+x)%p; x=(x+x)%p; y>>1; } return s%p; } int qpow(int x,int y) { int s=1; while(y) { if(y&1) s=qmul(s,x); x=qmul(x,x); y>>1; } return s%p; }

模板C++ 02数论算法 3排列与组合

2.3排列与组合 1.排列(在乎顺序) 全排列:n个人全部来排队,队长为n.第一个位置可以选n个,第二位置可以选n-1个,以此类推得:P(n,n)=n(n-1)(n-2)--3*2*1=n!(规定0!=1). 部分排列:n个人选m个来排队(m<=n).第一个位置可以选n个,第二位置可以选n-1个,以此类推,第m个(最后一个)可以选(n-m+1)个,得: 2.组合(不在乎顺序) n个人m(m<=n)个出来,不排队,不在乎顺序C(n,m).如果在乎排列那么就是P(n,m),如果不在乎那么就要除掉重

蓝桥杯- 算法训练 矩阵乘法

算法训练 矩阵乘法 时间限制:1.0s   内存限制:512.0MB 问题描述 输入两个矩阵,分别是m*s,s*n大小.输出两个矩阵相乘的结果. 输入格式 第一行,空格隔开的三个正整数m,s,n(均不超过200). 接下来m行,每行s个空格隔开的整数,表示矩阵A(i,j). 接下来s行,每行n个空格隔开的整数,表示矩阵B(i,j). 输出格式 m行,每行n个空格隔开的整数,输出相乘後的矩阵C(i,j)的值. 样例输入 2 3 21 0 -11 1 -30 31 23 1 样例输出 -3 2-8

算法导论-矩阵乘法-strassen算法

目录 1.矩阵相乘的朴素算法 2.矩阵相乘的strassen算法 3.完整测试代码c++ 4.性能分析 5.参考资料 内容 1.矩阵相乘的朴素算法 T(n) = Θ(n3) 朴素矩阵相乘算法,思想明了,编程实现简单.时间复杂度是Θ(n^3).伪码如下 1 for i ← 1 to n 2 do for j ← 1 to n 3 do c[i][j] ← 0 4 for k ← 1 to n 5 do c[i][j] ← c[i][j] + a[i][k]⋅ b[k][j] 2.矩阵相乘的stra

算法提高 矩阵乘法 区间dp

问题描述 有n个矩阵,大小分别为a0*a1, a1*a2, a2*a3, ..., a[n-1]*a[n],现要将它们依次相乘,只能使用结合率,求最少需要多少次运算. 两个大小分别为p*q和q*r的矩阵相乘时的运算次数计为p*q*r. 输入格式 输入的第一行包含一个整数n,表示矩阵的个数. 第二行包含n+1个数,表示给定的矩阵. 输出格式 输出一个整数,表示最少的运算次数. 样例输入 3 1 10 5 20 样例输出 150 数据规模和约定 1<=n<=1000, 1<=ai<=1

算法训练 矩阵乘法

问题描述 输入两个矩阵,分别是m*s,s*n大小.输出两个矩阵相乘的结果. 输入格式 第一行,空格隔开的三个正整数m,s,n(均不超过200). 接下来m行,每行s个空格隔开的整数,表示矩阵A(i,j). 接下来s行,每行n个空格隔开的整数,表示矩阵B(i,j). 输出格式 m行,每行n个空格隔开的整数,输出相乘後的矩阵C(i,j)的值. 样例输入 2 3 2 1 0 -1 1 1 -3 0 3 1 2 3 1 样例输出 -3 2 -8 2 提示 矩阵C应该是m行n列,其中C(i,j)等于矩阵A

第四章 分治策略 4.2 矩阵乘法的Strassen算法

package chap04_Divide_And_Conquer; import static org.junit.Assert.*; import java.util.Arrays; import org.junit.Test; /** * 矩阵相乘的算法 * * @author xiaojintao * */ public class MatrixOperation { /** * 普通的矩阵相乘算法,c=a*b.其中,a.b都是n*n的方阵 * * @param a * @param b

Spark中的矩阵乘法分析

前言: 矩阵乘法在数据挖掘/机器学习中是常用的计算步骤,并且在大数据计算中,shuffle过程是不可避免的,矩阵乘法的不同计算方式shuffle的数据量都不相同.通过对矩阵乘法不同计算方式的深入学习,希望能够对大数据算法实现的shuffle过程优化有所启发.网上有很多分布式矩阵乘法相关的文章和论文,但是鲜有对Spark中分布式矩阵乘法的分析.本文针对Spark中分布式矩阵乘法的实现进行必要的说明讨论. 分布式矩阵乘法原理: 矩阵乘法计算可以分为内积法和外积法.根据实现颗粒度的不同,也可以分为普通