HDU 5015 233 Matrix --矩陣快速冪


題意:給出矩陣的第0行(233,2333,23333,...)和第0列a1,a2,...an(n<=10,m<=10^9),給出式子: A[i][j] = A[i-1][j] + A[i][j-1],要求A[n][m]。

解法:看到n<=10和m<=10^9 應該對矩陣有些想法,現在我們假設要求A[a][b],則A[a][b] = A[a][b-1] + A[a-1][b] = A[a][b-1] + A[a-1][b-1] + A[a-2][b] = ...

這樣相當於右圖:,紅色部分為綠色部分之和,而頂上的綠色部分很好求,左邊的綠色部分(最多10個)其實就是:A[1][m-1],A[2][m-1]..A[n][m-1],即對每個1<=i<=n, A[i][m]都可由A[1][m-1],A[2][m-1]..A[n][m-1],於是建立12*12的矩陣:

,將中間矩陣求m-1次冪,與右邊[A[0][1],A[1][1]..A[n][1],3]^T相乘,結果就可以得出了。

代碼:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#define Mod 10000007
#define SMod Mod
#define lll __int64
using namespace std;

int n,m;
lll a[100006],sum[100005];

struct Matrix
{
    lll m[13][13];
    Matrix()
    {
        memset(m,0,sizeof(m));
        for(int i=1;i<=n+2;i++)
            m[i][i] = 1LL;
    }
};

Matrix Mul(Matrix a,Matrix b)
{
    Matrix res;
    int i,j,k;
    for(i=1;i<=n+2;i++)
    {
        for(j=1;j<=n+2;j++)
        {
            res.m[i][j] = 0;
            for(k=1;k<=n+2;k++)
                res.m[i][j] = (res.m[i][j]+(a.m[i][k]*b.m[k][j])%SMod + SMod)%SMod;
        }
    }
    return res;
}

Matrix fastm(Matrix a,int b)
{
    Matrix res;
    while(b)
    {
        if(b&1)
            res = Mul(res,a);
        a = Mul(a,a);
        b >>= 1;
    }
    return res;
}

int main()
{
    int i,j;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        sum[0] = 0;
        for(i=1;i<=n;i++)
        {
            scanf("%I64d",&a[i]);
            sum[i] = (sum[i-1] + a[i]);
        }
        lll suma = sum[n];
        if(m == 1)
        {
            printf("%I64d\n",(233LL+suma)%Mod);
            continue;
        }
        Matrix base;
        memset(base.m,0,sizeof(base.m));
        for(i=1;i<=n+1;i++)
            base.m[i][1] = 10LL;
        for(i=2;i<=n+1;i++)
        {
            for(j=2;j<=n+1;j++)
            {
                if(i >= j)
                    base.m[i][j] = 1LL;
            }
        }
        for(i=1;i<=n+2;i++)
            base.m[i][n+2] = 1LL;
        Matrix Right;
        memset(Right.m,0,sizeof(Right.m));
        Right.m[1][1] = 233LL;
        for(i=2;i<=n+1;i++)
            Right.m[i][1] = (233LL+sum[i-1])%Mod;
        Right.m[n+2][1] = 3LL;
        Matrix ans = fastm(base,m-1);
        ans = Mul(ans,Right);
        printf("%I64d\n",ans.m[n+1][1]%Mod);
    }
    return 0;
}
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM