zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    跳出iframe
    leetcode 225. Implement Stack using Queues
    leetcode 206. Reverse Linked List
    leetcode 205. Isomorphic Strings
    leetcode 203. Remove Linked List Elements
    leetcode 198. House Robber
    leetcode 190. Reverse Bits
    leetcode leetcode 783. Minimum Distance Between BST Nodes
    leetcode 202. Happy Number
    leetcode 389. Find the Difference
  • 原文地址:https://www.cnblogs.com/simplekinght/p/6674256.html
Copyright © 2011-2022 走看看