Uva10870 Recurrences(矩阵快速幂)

题目

考虑递推关系式\(f(n)=a1*f(n-1)+a2*f(n-2)+....+ad*f(n-d)\),计算f(n)%m

【输入格式】 输入包含多组测试数据。每组数据第一行为三个整数d,n,m(1<=d<=15,1<=n<=2^31-1,1<=m<=46340)。第二行包含d个非负整数a1,a2.....ad。第三行为d个非负整数f(1),f(2).....f(d)。这些数字均不超过2^31-1。输入结束的标志是d=n=m=0.

【输出格式】 对于每组数据,输出f(n)%m

思路

前置知识是矩阵乘法和矩阵快速幂。

矩阵相乘最重要的方法是一般矩阵乘积。它只有在第一个矩阵的栏数(column)和第二个矩阵的列数(row)相同时才有定义。一般单指矩阵乘积时,指的便是一般矩阵乘积。若A为m×n矩阵,B为n×p矩阵,则他们的乘积AB会是一个m×p矩阵。

公式

而矩阵快速幂对于n*n的方针多次进行自己乘自己的迭代运算,同样可以用数的快速幂优化。

举例来说,对于本题而言

设\(F[n]=(f[n-d+1],f[n-d+2],f[n-d+3]....f[n])\)

接下来要构造矩阵A,使得\(F[n]=F[n-1]*A\)

简单笔算一下可知:

这样代码也不难写出了,注意:矩阵相乘不满足交换律!!!!

代码

#include<bits/stdc++.h>
#define M 25
#define LL long long
using namespace std;
int d,x,mod;
struct Matrix{
    int n,m,a[M][M];
    void clear(){memset(a,0,sizeof(a));}
    void resize(int _n,int _m){n=_n;m=_m;}
    Matrix operator *(const Matrix &_)const{
        Matrix res;res.resize(n,_.m);
        for(int i=1;i<=n;i++){
            for(int j=1;j<=_.m;j++){
                res.a[i][j]=0;
                for(int k=1;k<=m;k++){
                    res.a[i][j]+=1LL*a[i][k]*_.a[k][j]%mod;
                    if(res.a[i][j]>=mod)res.a[i][j]-=mod;
                }
            }
        }
        return res;
    }
}Ma,F_d;
Matrix qkpow(Matrix a,int b){
    Matrix res;res.clear();res.resize(a.n,a.n);
    for(int i=1;i<=a.n;i++)res.a[i][i]=1;
    while(b){if(b&1)res=res*a;a=a*a;b>>=1;}
    return res;
}
int A[M],f[M];
int main(){
    while(scanf("%d%d%d",&d,&x,&mod)&&(d!=0&&x!=0&&mod!=0)){
        for(int i=1;i<=d;i++)scanf("%d",&A[i]),A[i]%=mod;
        for(int i=1;i<=d;i++)scanf("%d",&f[i]),f[i]%=mod;
        if(x<=d){printf("%d\n",f[x]);continue;}
        Ma.clear();Ma.resize(d,d);
        for(int i=2;i<=d;i++)Ma.a[i-1][i]=1;
        for(int i=1;i<=d;i++)Ma.a[d][i]=A[d-i+1];
        F_d.clear();F_d.resize(d,1);
        for(int i=1;i<=d;i++)F_d.a[i][1]=f[i];
        Matrix ans=qkpow(Ma,x-d)*F_d;
        printf("%d\n",ans.a[d][1]);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/zryabc/p/10359990.html

时间: 2024-10-12 18:36:15

Uva10870 Recurrences(矩阵快速幂)的相关文章

UVA 10870 - Recurrences(矩阵快速幂)

UVA 10870 - Recurrences 题目链接 题意:f(n) = a1 f(n - 1) + a2 f(n - 2) + a3 f(n - 3) + ... + ad f(n - d), for n > d. 已知前d项求第n项 思路:矩阵快速幂,对应矩阵为 |a1 a2 a3 ... ad| |1 0 0 ... 0 0 0| |0 1 0 ... 0 0 0| |0 0 1 ... 0 0 0| |0 0 0 ... 0 0 0| |0 0 0 ... 1 0 0| |0 0 0

UVA10870—Recurrences(简单矩阵快速幂)

题目链接:https://vjudge.net/problem/UVA-10870 题目意思: 给出a1,a2,a3,a4,a5------ad,然后算下面这个递推式子,简单的矩阵快速幂,裸题,但是第一个次遇到了矩阵大小不确定的矩阵快速幂,而且在这道题里面第一次明白了如何构造矩阵.算是矩阵快速幂的学习的一个小里程碑吧. f(n) = a1 *f(n - 1) + a2 *f(n - 2) + a3 *f(n - 3) + - + ad* f(n - d),  n > d.求f(n) 代码: 1

矩阵快速幂刷题系列

来源自http://blog.csdn.net/chenguolinblog/article/details/10309423 hdu 1575 Tr A Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5587    Accepted Submission(s): 4200 Problem Description A为一个方阵,则Tr

HDU 1757 A Simple Math Problem (矩阵快速幂)

[题目链接]:click here~~ [题目大意]: If x < 10 f(x) = x. If x >= 10 f(x) = a0 * f(x-1) + a1 * f(x-2) + a2 * f(x-3) + -- + a9 * f(x-10); 问f(k)%m的值. [思路]:矩阵快速幂,具体思路看代码吧,注意一些细节. 代码: #include<bits/stdc++.h> using namespace std; typedef long long LL; const

Codeforces Round #291 (Div. 2) E - Darth Vader and Tree (DP+矩阵快速幂)

这题想了好长时间,果断没思路..于是搜了一下题解.一看题解上的"快速幂"这俩字,不对..这仨字..犹如醍醐灌顶啊...因为x的范围是10^9,所以当时想的时候果断把dp递推这一方法抛弃了.我怎么就没想到矩阵快速幂呢.......还是太弱了..sad..100*100*100*log(10^9)的复杂度刚刚好. 于是,想到了矩阵快速幂后,一切就变得简单了.就可以把距离<=x的所有距离的点数都通过DP推出来,然后一个快速幂就解决了. 首先DP递推式很容易想到.递推代码如下: for(

POJ 3233 - Matrix Power Series ( 矩阵快速幂 + 二分)

POJ 3233 - Matrix Power Series ( 矩阵快速幂 + 二分) #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long LL; #define MAX_SIZE 30 #define CLR( a, b ) memset( a, b, sizeof(a) ) int MOD = 0; int n, k; st

HDU 4990 Reading comprehension(找规律+矩阵快速幂)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4990 Problem Description Read the program below carefully then answer the question. #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include<iostream> #include

hdu 6198(矩阵快速幂)

number number number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 175    Accepted Submission(s): 119 暴力发现当4 12 33 88 232 和斐波那契数列对比  答案为 第2*k+3个数减1 直接用矩阵快速幂求的F[2*k+3]  然后减1 A=1,B=0; 然后矩阵快速幂2*k

矩阵快速幂 模板与简单讲解

模板 快速幂模板 1 void solve(matrix t,long long o) 2 { 3 matrix e; 4 5 memset(e.a,0,sizeof(e.a)); 6 7 for (int i = 0;i < d;i++) 8 e.a[i][i] = 1; 9 10 while (o) 11 { 12 if (o & 1) 13 { 14 e = mul(e,t); 15 } 16 17 o >>= 1; 18 19 t = mul(t,t); 20 } 21