【HDU5015】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]。

分析

推单位矩阵,先开始没想出来,于是看了题解,但是没有看懂,只有又自己推,然后发现就推出来了诶

不要把菜当做不思考的借口

第0列是告诉了的,忽略,从第1列开始看,第一列是

233   

a1

a2

a3

a4

...

an

观察到第二列是2333,会出现一个3,于是我们干脆在每一列后面补一个3方便递推

于是第一列和第二列分别是

233                                                              2333

a1                                                                             2333+a1

a2                                                                             2333+a1+a2

a3                                                                             2333+a1+a2+a3

a4                                                                             2333+a1+a2+a3+a4

...                                                                 ...

an                                                                             2333+a1+a2+...+an-1+an

3                                                                  3

想从第一列得到第二列,那需要乘什么呢?肯定是个n+2行n+2列的矩阵

直接推发现2333=233*10+3

于是第一行10 0 0 ...0 0 1

2333+a1=233*10+3+a1

于是第二行 10 1 0 ... 0 0 1

类推可得到单位矩阵

10 0 0 ...0 0 1

10 1 0 ...0 0 1

10 1 1 ...0 0 1

10 1 1 ...1 0 1

10 1 1 ...1 1 1

0 0 0 ... 0 0 1

将这个矩阵求m-1次方再与原来的第一列相乘,就可求出A[n][m],第1列用第0列推出

或者是直接用第0列,求m次方

代码

#include<bits/stdc++.h>
using namespace std;
#define N 15
#define ll long long
#define mod 10000007
ll n,m,f;
ll one[N];
struct email
{
    ll x[N][N];
}a,ans;

inline void init()
{
    one[0]=23;one[n+1]=3;
    for(ll i=1;i<=n;i++)scanf("%lld",&one[i]);
    memset(a.x,0,sizeof(a.x));
    for(ll i=0;i<=n;i++)a.x[i][0]=10,a.x[i][n+1]=1;
    a.x[n+1][n+1]=1;
    for(ll i=1;i<=n;i++)
        for(ll j=1;j<=i;j++)
            a.x[i][j]=1;
}

inline email mul(email a,email b)
{
    email c;
    memset(c.x,0,sizeof(c.x));
    for(ll i=0;i<=n+1;i++)
        for(ll j=0;j<=n+1;j++)
            for(ll k=0;k<=n+1;k++)
                c.x[i][j]+=a.x[i][k]*b.x[k][j],c.x[i][j]%=mod;
    return c;
}

inline email ksm(email a,ll m)
{
    if(m==1)return a;
    email b=ksm(a,m/2);
    b=mul(b,b);
    if(m&1)b=mul(b,a);
    return b;
}

int main()
{
    while(scanf("%lld%lld",&n,&m)==2)
    {
        init();
        ans=ksm(a,m);f=0;
        for(ll i=0;i<=n+1;i++)
            f+=ans.x[n][i]*one[i],f%=mod;
        printf("%lld\n",f);
    }
    return 0;
}

 

posted @ 2018-11-03 23:46  WJEMail  阅读(163)  评论(0编辑  收藏  举报