Codeforces 392C Yet Another Number Sequence (矩阵快速幂+二项式展开)

题意:已知斐波那契数列fib(i) , 给你n 和 k , 求∑fib(i)*ik (1<=i<=n)

思路:不得不说,这道题很有意思,首先我们根据以往得出的一个经验,当我们遇到 X^k 的形式,当 X 很大,k很小时,我们可以利用二项式定理进行展开,然后求出递推式在利用矩阵加速

推导过程:

已知 fib(1) = 1, fib(2) = 1,fib(i) = fib(i-1) + fib(i-2);

       Ai(k) =fib(i)*i^k;

根据数学归纳法,我们可知 fib(i+1)*(i+1)^k = ( fib(i) + fib(i-1) ) * (i+1)^k 必然成立

将上式进行二项式展开 

上式 = ( fib(i) + fib(i-1) ) * {C[k][0]*i^0 + C[k][1]*i^1 +...+C[k][k]*i^k}; 

       = C[k][0]*(i^0* fib(i) + i^0*fib(i-1) ) + C[k][1]*(i^1* fib(i) + i^1*fib(i-1) )....(乘法结合律

我们定义 g1[i][a] = fib(i)*i^a , g2[i][a] = fib(i-1)*i^a

将定义的g1 , g2 带入上式中得到递推公式

g1[i][k] = C[k][0]*(g1[i-1][0]+g2[i-1][0])+C[k][1]*(g1[i-1][1]+g2[i-1][1])+...+C[k][k](g1[i-1][k]+g2[i-1][k]);

g2[i][k]= C[k][0]*g1[i-1][0] +C[k][1]*g1[i-1][1]+..+C[k][k]*g1[i-1][k];

最后再根据递推式写出构造矩阵即可

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#define ll long long
using namespace std;
ll N,M,P;
const ll MOD=1000000007;
ll C[85][85];
struct  Matrix
{
    ll m[85][85];
};

Matrix  A;

Matrix  I;

void get_C()
{
    memset(C,0,sizeof(C));
    C[0][0]=1;
    for(int i=1;i<=82;i++)
    {
        C[0][i]=C[i][i]=1;
        for(int j=1;j<=i;j++)
        {
            C[j][i]=(C[j][i-1]+C[j-1][i-1])%MOD;
        }
    }
}

void make_I(int k)
{
    memset(I.m,0,sizeof(I.m));
    for(int i=0;i<=2*(k+1);i++)
      for(int j=0;j<=2*(k+1)+1;j++)
       if(i==j)
       I.m[i][j]=1;
}

void make_A(int k)
{
    memset(A.m,0,sizeof(A.m));
    for(int i=0;i<=k;i++)
    {
        for(int j=0;j<=i;j++)
        {
            A.m[i][j]=C[j][i];
        }
    }
    for(int i=0;i<=k;i++)
    {
        for(int j=0;j<=i;j++)
        {
            A.m[i+k+1][j]=C[j][i];
        }
    }
    for(int i=0;i<=k;i++)
    {
        for(int j=k+1;j<=2*(k+1)-1;j++)
        {
            A.m[i][j]=C[j-k-1][i];
        }
    }
    A.m[2*(k+1)][k]=1;
    A.m[2*(k+1)][2*(k+1)]=1;
}

Matrix multi(Matrix a,Matrix b)
{
    Matrix ans;
    for(int i=0;i<=N;i++)
    {
       for(int j=0;j<=M;j++)
       {
          ans.m[i][j]=0;
          for(int k=0;k<=P;k++)
          {
             ans.m[i][j]=(ans.m[i][j]+a.m[i][k]*b.m[k][j])%MOD;
          }
          ans.m[i][j]%=MOD;
       }
    }
    return ans;
}

Matrix power(Matrix a,ll k)
{
    Matrix ans=I,p=a;
    while(k)
    {
      if(k&1)
      {
        ans=multi(ans,p);
      }
      k>>=1;
      p=multi(p,p);
    }
    return ans;
}

int main()
{
    ll n;
    int k;
    get_C();
    while(cin>>n>>k)
    {
        if(n==1)
        {
            cout<<"1"<<endl;
            continue;
        }
        else
        {
            make_A(k);
            make_I(k);
            N=M=P=2*(k+1);
            Matrix ans = power(A,n);
            ll num=0;
            for(int i=0;i<M;i++)
            num=(num+ans.m[2*(k+1)][i])%MOD;
            cout<<num<<endl;
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/simplekinght/p/6674256.html