FZU_1683 矩阵快速幂 求和

这个题目确实是很简单的一个矩阵快速幂,但是我在求和的时候,用的是标准的求和,即,一共计算logN次Ak,但是这样会超时。

后来就发现原来本身和Sn=Sn-1+Fn;即Sn本身可以写在矩阵当中,所以直接求一次 Ak就能得出结果。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
using namespace std;
struct Mat{
 int mat[4][4];
};
Mat it,E,E0;
void init()
{
    memset(it.mat,0,sizeof (Mat));
    memset(E.mat,0,sizeof (Mat));
    memset(E0.mat,0,sizeof (Mat));
    for (int i=0;i<4;i++)
        E.mat[i][i]=1;
    it.mat[0][0]=1;
    it.mat[0][1]=3;
    it.mat[0][2]=2;
    it.mat[0][3]=7;

    it.mat[1][1]=3;
    it.mat[1][2]=2;
    it.mat[1][3]=7;

    it.mat[2][1]=1;
    it.mat[3][2]=1;
}
Mat operator*(Mat a,Mat b)
{
    Mat c;
    c=E0;
    for (int i=0;i<4;i++)
        for (int j=0;j<4;j++)
        for (int k=0;k<4;k++)
    {
        if (a.mat[i][k] && b.mat[k][j])
        {
            c.mat[i][j]+=a.mat[i][k]*b.mat[k][j];
            c.mat[i][j]%=2009;
        }
    }
    return c;
}
Mat operator^(Mat a,int x)
{
    Mat c=E;
    for (;x;x>>=1)
    {
        if (x&1)
            c=c*a;
        a=a*a;
    }
    return c;
}

int main()
{
    init();
    int t;
    scanf("%d",&t);
    int counts=0;
    while (t--)
    {
        int n;
        scanf("%d",&n);
        int ans=0;
        printf("Case %d: ",++counts);
        if (n>=3){
        Mat s=it^(n-2);
        ans=s.mat[0][0]*9+s.mat[0][1]*5+s.mat[0][2]*3+s.mat[0][3];
        ans%=2009;
        }
        if (n==0) ans=1;
        if (n==1) ans=3;
        if (n==2) ans=5;
        printf("%d\n",ans);
    }
    return 0;
}

 

posted @ 2013-11-22 19:44  KRisen  阅读(469)  评论(0编辑  收藏  举报