• 【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
    ",f);
        }
        return 0;
    }
  • 相关阅读:
    Openjudge 1.3 算数表达式与顺序执行
    Openjudge 1.2 变量定义、赋值并转换
    Openjudge 1.4 逻辑表达式与条件分支
    Openjudge 1.5 循环控制
    Openjudge 1.6 一位数组
    Openjudge 1.8 多维数组
    poj-3134 ida*||记录路径bfs
    wust-1588 日期模拟题
    wust 1599弗洛伊德
    hdu5667 费马小定理加矩阵快速幂
  • 原文地址:https://www.cnblogs.com/NSD-email0820/p/9899540.html
Copyright © 2020-2023  润新知