UVA - 10870 Recurrences(构造矩阵)

传送门

Consider recurrent functions of the following form:
f(n) = a1f(n − 1) + a2f(n − 2) + a3f(n − 3) + … + adf(n − d), for n > d,
where a1, a2, … , ad are arbitrary constants.
A famous example is the Fibonacci sequence, defined as: f(1) = 1, f(2) = 1, f(n) = f(n − 1) +
f(n − 2). Here d = 2, a1 = 1, a2 = 1.
Every such function is completely described by specifying d (which is called the order of recurrence),
values of d coefficients: a1, a2, … , ad, and values of f(1), f(2), … , f(d). You’ll be given these numbers,
and two integers n and m. Your program’s job is to compute f(n) modulo m.
Input
Input file contains several test cases. Each test case begins with three integers: d, n, m, followed by
two sets of d non-negative integers. The first set contains coefficients: a1, a2, … , ad. The second set
gives values of f(1), f(2), … , f(d).
You can assume that: 1 ≤ d ≤ 15, 1 ≤ n ≤ 2
31 − 1, 1 ≤ m ≤ 46340. All numbers in the input will
fit in signed 32-bit integer.
Input is terminated by line containing three zeroes instead of d, n, m. Two consecutive test cases
are separated by a blank line.
Output
For each test case, print the value of f(n)( mod m) on a separate line. It must be a non-negative integer,
less than m.
Sample Input
1 1 100
2
1
2 10 100
1 1
1 1
3 2147483647 12345
12345678 0 12345
1 2 3
0 0 0
Sample Output
1
55
423

题目大意:
给定一个递推关系式

f(n)=a1f(n1)+a2f(n2)+a3f(n3)+...+adf(nd)
让你求f(n)%m,d,n,m是已知的,a[i]和f[1-d]是已知的(1 ≤ d ≤ 15, 1 ≤ n ≤ 2^31 − 1, 1 ≤ m ≤ 46340. )

解题思路:
我们可以拿斐波那契数列来举例构造一个矩阵,

f(n)=f(n1)f(n2)

那么我们可以构造一个矩阵A(2*2)的矩阵。
(f(n1),f(n2))A=(f(n),f(n1))

又因为
f(n)=f(n1)+f(n2)

所以可以求得矩阵A=
[1110]

F(n)=(f(n),f(n1))

F(n)=F(2)An2

其实 根据上边这个斐波那契,我们可以做这道题了。首先还是要构造一个矩阵

(f(n1),f(n2)...f(nd))A=(f(n),f(n1)...f(nd+1))

其实我们很容易想到A矩阵是一个d*d的矩阵。它的具体值有
1a2a3...ad1ad100...00010...00..................000...00000...10

那么这个f(n)就可以表示了:
F(n)=(f(n),f(n1),f(n2)...f(nd))

F(n)=F(d)And

那么f(n)=F(d).(0,0)
然后就是一个矩阵的快速幂和矩阵乘法来求了:
具体看代码:
My Code:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long LL;
LL d, n, MOD;
const int MAXN = 20;
LL a[MAXN], f[MAXN];
typedef struct
{
    LL mat[MAXN][MAXN];
}Matrix;
Matrix Init()
{
    Matrix I;
    for(int i=0; i<d; i++)
    {
        for(int j=0; j<d; j++)
        {
            if(i == j)
                I.mat[i][j] = 1;
            else
                I.mat[i][j] = 0;
        }
    }
    return I;
}
Matrix Mul_Matrix(Matrix a, Matrix b)
{
    Matrix c;
    for(int i=0; i<d; i++)
    {
        for(int j=0; j<d; j++)
        {
            c.mat[i][j] = 0;
            for(int k=0; k<d; k++)
            {
                c.mat[i][j] += a.mat[i][k]*b.mat[k][j];
                c.mat[i][j] %= MOD;
            }
        }
    }
    return c;
}
Matrix quick_MOD_Matrix(LL m, Matrix a)
{
    Matrix I = Init();
    Matrix ans = I;
    while(m)
    {
        if(m&1)
            ans = Mul_Matrix(ans, a);
        m>>=1;
        a = Mul_Matrix(a, a);
    }
    return ans;
}
int main()
{
    while(cin>>d>>n>>MOD)
    {
        if(d==0 && n==0 && MOD==0)
            break;
        Matrix P;
        for(int i=0; i<d; i++)
            cin>>P.mat[i][0];
        for(int i=d-1; i>=0; i--)///方便
            cin>>f[i];
        if(n < d)
        {
            cout<<f[n]<<endl;
            continue;
        }
        for(int i=0; i<d; i++)
        {
            for(int j=1; j<d; j++)
            {
                if(i==j-1)
                    P.mat[i][j] = 1;
                else
                    P.mat[i][j] = 0;
            }
        }
        Matrix tmp = quick_MOD_Matrix(n-d,P);
        LL ans = 0;
        for(int i=0; i<d; i++)
        {
            ans += tmp.mat[i][0]*f[i];
            ans %= MOD;
        }
        ans = (ans%MOD+MOD)%MOD;
        cout<<ans<<endl;
    }
    return 0;
}

你可能感兴趣的:(构造矩阵,矩阵乘法)