Uva 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) = a1*f(n-1) + a2*f(n-2) + … + ad*f(n-d);题意已知n, m, d, ai和f(1)~f(d);
计算最后f(n)%m.

解题思路:
1.
f(n) = a1*f(n-1) + a2*f(n-2) + … + ad*f(n-d); 拆分成矩阵ax=b形式;
计算得: [ad, ad-1, ad-2, …, a2, a1] (行向量) * [f(n-d), …, f(n-1)] (列向量) = f(n);
2.
A*F(n-1) = F(n)有下列式子
0 1 0 … 0 0 f(n-d-1) f(n-d)
0 0 1 … 0 0 … …
…….. * … = …
0 0 0 … 0 1 f(n-2) f(n-1)
ad ad-1 .… a2 a1 f(n-1) f(n)
3.
F(n) =A*F(n-1), F(n-1) = A*F(n-2), …. , F(d+1)=A*F(d);

矩阵优化,ac代码如下:

///@zhangxiaoyu
///2015/8/14

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
using namespace std;
typedef long long LL;
const LL maxn=16;

LL d;
LL a[maxn];
LL f[maxn];
struct matrix{
   LL arr[maxn][maxn];
}Unit;

matrix mul(matrix a,matrix b,LL n,LL mod)
{
    LL i,j,k,temp;
    matrix val;
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=n;j++)
        {
            temp=0;
            for(k=1;k<=n;k++)
            {
                temp=(temp+(a.arr[i][k]%mod*b.arr[k][j]%mod)%mod)%mod;
                val.arr[i][j]=temp;
            }
        }
    }
    return val;
}

matrix matrixPow(matrix a,LL n,LL m,LL mod)
{
    matrix res=Unit,temp;
    temp=a;
    for(;m;m/=2)
    {
        if(m&1)
            res=mul(res,temp,n,mod);
        temp=mul(temp,temp,n,mod);
    }
    return res;
}

void init(LL n)
{
    LL i;
    memset(Unit.arr,0,sizeof(Unit.arr));
    for(i=1;i<=n;i++)
        Unit.arr[i][i]=1;
}

int main()
{
    LL m,n,i,j;
    while(~scanf("%lld%lld%lld",&d,&n,&m))
    {
        if(d==0&&n==0&&m==0)
            break;
        LL ans=0;
        matrix maze;
        matrix temp;
        memset(temp.arr,0,sizeof(temp.arr));
        memset(maze.arr,0,sizeof(maze.arr));
        init(d);
        for(i=1;i<=d;i++)
        {
            scanf("%lld",&a[i]);
        }
        for(i=1;i<=d;i++)
        {
            scanf("%lld",&f[i]);
        }
        for(i=1;i<=d-1;i++)
        {
            j=i+1;
            maze.arr[i][j]=1;
        }
        for(i=1;i<=d;i++)
        {
            maze.arr[d][i]=a[d-i+1];
        }
      /* for(i=1;i<=d;i++) { for(j=1;j<=d;j++) { printf("%I64d ",maze.arr[i][j]); } puts(""); } */
        temp=matrixPow(maze,d,n-d,m);
        ///prLLf("%d\n",temp.arr[1][1]);
        /* for(i=1;i<=d;i++) { for(j=1;j<=d;j++) { printf("%I64d ",temp.arr[i][j]); } puts(""); } */
        for(i=1;i<=d;i++)
        {
            ans+=(temp.arr[d][i]*f[i]%m);
            ans%=m;
        }
        printf("%lld\n",ans%m);
    }
    return 0;
}

你可能感兴趣的:(Uva Recurrences 矩阵优化)