HDU 3306 - Another kind of Fibonacci

给你 A(0) = 1 , A(1) = 1 , A(N) = X * A(N - 1) + Y * A(N - 2) (N >= 2).

求 S(N) = A(0) 2 +A(1) 2+……+A(n) 2.

 

 

由于线性代数只能做线性变换,故要得出 A(n) 2 的递推式

A(n) =X2A(N-1)2+Y2A(N-2)2+2XYA(N-1)A(N-2);

难点就在于 A(N-1)A(N-2) 这一项

故找到此项递推式

A(N-1)A(N-2) = (XA(N-2)+YA(N-3))*A(N-2) = XA(N-2)2+YA(N-2) A(N-3);

就可以写成矩阵

|1 X2 Y2 2XY|    |  S(n-1)        |  |  S(n)           |

|0 X2 Y2 2XY| * |  A(n-1)2        | = |  A(n)2           |

|0 0   1   0   |    |A(n-2)2          |   |A(n-1)2         |

|0 0   X   Y   |    |A(n-2)A(n-3)|   |A(n-1)A(n-2)|

 

剩下就是矩阵快速幂了

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
struct P{
    int a[65][65];
}c,s,q;
int n,k,mod;
int a[35][35];
void ini()
{
    memset(s.a,0,sizeof(s.a));
    for(int i=1;i<=n;i++) s.a[i][i]=1;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            s.a[i][j+n]=s.a[i+n][j+n]=a[i][j];
    memset(q.a,0,sizeof(q.a));
    for(int i=1;i<=n;i++) q.a[i+n][i]=1;
}
P mult(const P& a,const P& b)
{
    P c;
    for(int i=1;i<=2*n;++i)
    {
        for(int j=1;j<=2*n;++j)
        {
            c.a[i][j]=0;
            for(int k=1;k<=2*n;k++)
                c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j] )%mod;
        }
    }
    return c;
}
void fuc(int p)
{
    memset(c.a,0,sizeof(c.a));
    for(int i=1;i<=n*2;i++) c.a[i][i]=1;
    while(p)
    {
        if(p&1) c=mult(c,s);
        s=mult(s,s);
        p>>=1;
    }
}
int main()
{
    while(~scanf("%d%d%d",&n,&k,&mod))
    {
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                scanf("%d",&a[i][j]);
                a[i][j]%mod;
            }
        }
        ini();
        fuc(k);
        P ans;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                ans.a[i][j]=0;
                for(int k=i;k<=2*n;k++)
                    ans.a[i][j]=(ans.a[i][j]+c.a[i][k]*q.a[k][j] )%mod;                
            }
        }        
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++) printf("%d ",ans.a[i][j]);
            puts("");
        }
    }
} 

 

posted @ 2016-07-06 10:57  nicetomeetu  阅读(140)  评论(0编辑  收藏  举报