【矩阵乘法】【codevs 1250】Fibonacci数列

1250 Fibonacci数列

 时间限制: 1 s
 空间限制: 128000 KB
 题目等级 : 钻石 Diamond

题目描述 Description

定义:f0=f1=1, fn=fn-1+fn-2(n>=2)。{fi}称为Fibonacci数列。

输入n,求fn mod q。其中1<=q<=30000。

输入描述 Input Description

第一行一个数T(1<=T<=10000)。
以下T行,每行两个数,n,q(n<=10^9, 1<=q<=30000)

输出描述 Output Description

文件包含T行,每行对应一个答案。

样例输入 Sample Input

3
6 2
7 3
7 11

样例输出 Sample Output

1
0
10

数据范围及提示 Data Size & Hint

1<=T<=10000
n<=10^9, 1<=q<=30000

题解:

因为n是10^9,所以不能用朴素的O(n)的地推来解决,我们需要具有更加优秀复杂度的算法——矩阵乘来帮助。

先简单介绍一下它:

矩阵乘是O(logn)的复杂度,针对的对象是一个n行m列和一个m行p列的矩阵。矩阵乘所得到的就是一个n行p列的矩阵,这个矩阵的第i行第j列是由一个矩阵的第i行的每一个数与另一个矩阵的第j列的对应数乘积的加和。一般的情况下,我们可以用快速幂来进行加速。

朴素的矩阵乘:

for (int i=1; i<=n; i++)
        for (int j=1; j<=p; j++)
            for (int k=1; k<=m; k++)
                c[i][j]+=a[i][k]*b[k][j];

回归问题,我们需要求的是Fibonacci数列的第n项,可以建立两个矩阵:

然后让它们两个相乘,我们可以得到这样的矩阵:

于是我们可以发现,对于f[n]而言,它实际上可以由这样两个矩阵转移来,而对于B矩阵,它也是由上一层转移来的,所以对于f[n]来说,它可以这样得到:

于是可以应用快速幂加速下的矩阵乘来解决。(传参时各种奇怪问题希望大家小心一下。。。)

Code:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int T,n,q,ans,a[2][2],b[2][2];
int in(){
    int x=0; char ch=getchar();
    while (ch<‘0‘ || ch>‘9‘) ch=getchar();
    while (ch>=‘0‘ && ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar();
    return x;
}
void init(){
    a[0][0]=a[0][1]=a[1][0]=1; a[1][1]=0;
    b[0][0]=b[0][1]=b[1][0]=1; b[1][1]=0;
}
void matrix(int x[2][2],int y[2][2]){
    int c[2][2]={0};
    for (int i=0; i<=1; i++)
        for (int j=0; j<=1; j++)
            for (int k=0; k<=1; k++)
                c[i][j]=(c[i][j]+x[i][k]*y[k][j])%q;
    for (int i=0; i<=1; i++)
        for (int j=0; j<=1; j++)
            y[i][j]=c[i][j];
}
int main(){
    T=in();
    while (T--){
        n=in(),q=in();
        init();
        if (n<=1){
            printf("1\n");
            continue;
        }
        int y=n-2;
        while (y){
            if (y&1) matrix(a,b);
            y>>=1; matrix(a,a);
        }
        ans=(b[0][0]+b[0][1])%q;
        printf("%d\n",ans);
    }
    return 0;
}
时间: 2024-10-12 12:09:27

【矩阵乘法】【codevs 1250】Fibonacci数列的相关文章

矩阵乘法快速幂 codevs 1250 Fibonacci数列

codevs 1250 Fibonacci数列 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 定义:f0=f1=1, fn=fn-1+fn-2(n>=2).{fi}称为Fibonacci数列. 输入n,求fn mod q.其中1<=q<=30000. 输入描述 Input Description 第一行一个数T(1<=T<=10000). 以下T行,每行两个数,n,q(n<=109, 1<

矩阵乘法快速幂 codevs 1732 Fibonacci数列 2

1732 Fibonacci数列 2 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 Description 在“1250 Fibonacci数列”中,我们求出了第n个Fibonacci数列的值.但是1250中,n<=109.现在,你的任务仍然是求出第n个Fibonacci数列的值,但是注意:n为整数,且1 <= n <= 100000000000000 输入描述 Input Description 输入有多组数据,每

1250 Fibonacci数列(矩阵乘法快速幂)

1250 Fibonacci数列 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 定义:f0=f1=1, fn=fn-1+fn-2(n>=2).{fi}称为Fibonacci数列. 输入n,求fn mod q.其中1<=q<=30000. 输入描述 Input Description 第一行一个数T(1<=T<=10000). 以下T行,每行两个数,n,q(n<=109, 1<=q<=

1250 Fibonacci数列

1250 Fibonacci数列 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 Description 定义:f0=f1=1, fn=fn-1+fn-2(n>=2).{fi}称为Fibonacci数列. 输入n,求fn mod q.其中1<=q<=30000. 输入描述 Input Description 第一行一个数T(1<=T<=10000). 以下T行,每行两个数,n,q(n<=109, 1&

那条矩阵乘法的不归路——数列

话说今天搜矩阵相乘,没有一个人用pascal写,是不是学到矩阵相乘的孩子都果断转c++了...我可是有良心的写博人,当然附上pascal代码 故事开始了 今天看到这样一个题 a[1]=a[2]=a[3]=1 a[x]=a[x-3]+a[x-1]  (x>3) 求a数列的第n项对1000000007(10^9+7)取余的值. 然后是它的数据范围 对于30%的数据 n<=100: 对于60%的数据 n<=2*10^7: 对于100%的数据 T<=100,n<=2*10^9: 当我

poj 3070 Fibonacci(矩阵快速幂求Fibonacci数列)

题目链接: http://poj.org/problem?id=3070 题意: 我们知道斐波那契数列0 1 1 2 3 5 8 13-- 数列中的第i位为第i-1位和第i-2位的和(规定第0位为0,第一位为1). 求斐波那契数列中的第n位mod 10000的值. 思路: 这里的n很大,有10^9,for一遍肯定是不可以的. 所以要用矩阵乘法求斐波那契数列. f[n+1] = f[n]+f[n-1] f[n] = f[n] 构造以下矩阵,n次幂,mat[1][0] 就是答案 1 1 1 0 求矩

矩阵乘法 codevs 1287 矩阵乘法

1287 矩阵乘法 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 小明最近在为线性代数而头疼,线性代数确实很抽象(也很无聊),可惜他的老师正在讲这矩阵乘法这一段内容.当然,小明上课打瞌睡也没问题,但线性代数的习题可是很可怕的.小明希望你来帮他完成这个任务. 现在给你一个ai行aj列的矩阵和一个bi行bj列的矩阵,要你求出他们相乘的积(当然也是矩阵).(输入数据保证aj=bi,不需要判断) 矩阵乘法的定义: 1. 矩阵A乘以B的

利用矩阵乘法计算递推数列的某一项

1732 Fibonacci数列 2

1732 Fibonacci数列 2 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 题目描述 Description 在“1250 Fibonacci数列”中,我们求出了第n个Fibonacci数列的值.但是1250中,n<=109.现在,你的任务仍然是求出第n个Fibonacci数列的值,但是注意:n为整数,且1 <= n <= 100000000000000 输入描述 Input Description 输入有多组数据,每组数据占一行,