CSU 1208: Fibonacci sum

题目链接:http://122.207.68.93/OnlineJudge/problem.php?id=1208

比赛的时候只是觉得是矩阵,但是一直没想到怎么推...(a+b)^k应该联想到二项式的啊ToT,而且他说k<=20,明摆着就是告诉你可以矩阵的...正确的构造方法是:

                                                                                     C(k,0)  c(k-1,0)  C(k-2,0)...C(0,0) C(k,0)

                                C(k,1)  c(k-1,1)  C(k-2,1)...    0    C(k,1)

[ fib(n-1)k,fib(n-1)k-1fib(2).....fib(n-2)k,sum[n-1] ] *        .......

                                  C(k,k)       0             0    ...     0    C(k,K)

                                   0          0             0    ...     0        1  

CSU 1208
#include
#include<string.h>
#define MOD 1000000007
#define maxn 25
long long C[25][25];
long long ret[maxn][maxn];
long long init[maxn][maxn];
long long buf[maxn][maxn];

void matrixMul(long long a[][maxn] , long long b[][maxn] , long long n,long long mod)
{
    long long i,j,k;
    for(i=0;i)
    {
        for(j=0;j)
        {
            buf[i][j]=0;
        }
    }
    for(i=0;i)
    {
        for(k=0;k)
        {
            if(a[i][k]==0)
                continue;
            for(j=0;j)
            {
                if(b[k][j]==0)
                    continue;
                buf[i][j]+=a[i][k]*b[k][j];
                if (buf[i][j]>=mod||buf[i][j]<=-mod)
                {
                    buf[i][j]%=mod;
                }
            }
        }
    }
    for(i=0;i)
    {
        for(j=0;j)
        {
            a[i][j]=buf[i][j];
        }
    }
}

void matrixMul(long long n,long long m,long long mod)
{
    long long i,j;
    for(i=0;i)
    {
        for(j=0;j)
        {
            ret[i][j]=(i==j);
        }
    }
    for(;m;m>>=1)
    {
        if(m&1)
        {
            matrixMul(ret,init,n,mod);
        }
        matrixMul(init,init,n,mod);
    }
}

void initc()
{
    C[0][0]=C[1][0]=C[1][1]=1;
     for(int i=2;i<=20;i++)
     {
         for(int j=0;j<=i&&j<=20;j++)
         {
             if(j==0)
                 C[i][j]=1;
             else
                 C[i][j]=(C[i-1][j]+C[i-1][j-1])%MOD;
         }
     }
}

int main()
{
    initc();
    int t,n,k,i,j;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&k);
        if(n==1)
        {
            printf("1\n");
            continue;
        }
        else if(n==2)
        {
            printf("2\n");
            continue;
        }
        memset(init,0,sizeof(init));
        for(i=0;i<=k;i++)
        {
            for(j=0;j<=k-i;j++)
            {
                init[j][i]=C[k-i][j];
            }
        }
        for(i=0;i<=k;i++)
        {
            init[i][k+1]=C[k][i];
        }
        init[k+1][k+1]=1;
        matrixMul(k+2,n-2,MOD);
        long long ans=0;
        for(i=0;i<=k;i++)
        {
            ans=(ans+ret[i][k+1])%MOD;
        }
        ans=(ans+2*ret[k+1][k+1])%MOD;
        printf("%lld\n",ans);
    }
    return 0;
}

 

  哎,以此题为记,不能再被表面现象吓到了><           

 

下面为升级版,可以用做练习:

hdu 3509.Buge's Fibonacci Number Problem

HDU 3509
#include
#include<string.h>
int MOD;
#define maxn 55
long long C[55][55],A[55],B[55],F1[55],F2[55];
long long ret[maxn][maxn];
long long init[maxn][maxn];
long long buf[maxn][maxn];

void matrixMul(long long a[][maxn] , long long b[][maxn] , long long n,long long mod)
{
    long long i,j,k;
    for(i=0;i)
    {
        for(j=0;j)
        {
            buf[i][j]=0;
        }
    }
    for(i=0;i)
    {
        for(k=0;k)
        {
            if(a[i][k]==0)
                continue;
            for(j=0;j)
            {
                if(b[k][j]==0)
                    continue;
                buf[i][j]+=a[i][k]*b[k][j];
                if (buf[i][j]>=mod||buf[i][j]<=-mod)
                {
                    buf[i][j]%=mod;
                }
            }
        }
    }
    for(i=0;i)
    {
        for(j=0;j)
        {
            a[i][j]=buf[i][j];
        }
    }
}

void matrixMul(long long n,long long m,long long mod)
{
    long long i,j;
    for(i=0;i)
    {
        for(j=0;j)
        {
            ret[i][j]=(i==j);
        }
    }
    for(;m;m>>=1)
    {
        if(m&1)
        {
            matrixMul(ret,init,n,mod);
        }
        matrixMul(init,init,n,mod);
    }
}

void initc(int k)
{
    C[0][0]=C[1][0]=C[1][1]=1;
     for(int i=2;i<=k;i++)
     {
         for(int j=0;j<=i&&j<=k;j++)
         {
             if(j==0)
                 C[i][j]=1;
             else
                 C[i][j]=(C[i-1][j]+C[i-1][j-1])%MOD;
         }
     }
}


int main()
{
    long long t,n,k,i,j,f1,f2,a,b;
    scanf("%I64d",&t);
    while(t--)
    {
        scanf("%I64d%I64d%I64d%I64d%I64d%I64d%I64d",&f1,&f2,&a,&b,&k,&n,&MOD);
        initc(k);
        long long ans=0;
        F1[0]=F2[0]=1;
        for(i=1;i<=k;i++)
        {
            F1[i]=(F1[i-1]*f1)%MOD;
            F2[i]=(F2[i-1]*f2)%MOD;
        }
        if(n==1)
        {
            ans=F1[k];
            printf("%I64d\n",ans);
            continue;
        }
        else if(n==2)
        {
            ans=F1[k];
            ans=(ans+F2[k])%MOD;
            printf("%I64d\n",ans);
            continue;
        }
        memset(init,0,sizeof(init));
        A[0]=B[0]=1;
        for(i=1;i<=k;i++)
        {
            A[i]=(A[i-1]*a)%MOD;
            B[i]=(B[i-1]*b)%MOD;
        }
        for(i=0;i<=k;i++)
        {
            for(j=0;j<=k-i;j++)
            {
                if(j>k-i)
                    init[j][i]=0;
                else
                    init[j][i]=((C[k-i][j]*A[k-i-j])%MOD*B[j])%MOD;
            }
        }
        for(i=0;i<=k;i++)
        {
            init[i][k+1]=((C[k][i]*A[k-i])%MOD*B[i])%MOD;
        }
        init[k+1][k+1]=1;
        matrixMul(k+2,n-2,MOD);
        for(i=0;i<=k;i++)
        {
            ans=(ans+((F2[k-i]*F1[i])%MOD)*ret[i][k+1])%MOD;
        }
        long long temp;
        temp=F1[k];
        temp=(temp+F2[k])%MOD;
        ans=(ans+(temp*ret[k+1][k+1])%MOD)%MOD;
        printf("%I64d\n",ans);
    }
    return 0;
}

 

 

                     

转载于:https://www.cnblogs.com/SolarWings/archive/2013/04/04/3000279.html

你可能感兴趣的:(CSU 1208: Fibonacci sum)