1. 程式人生 > >【HDU5015】233 Matrix

【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;
}