HDU 5015 233 Matrix(构造矩阵)

题目链接:
HDU 5015 233 Matrix

/*
 * 题意:
 * 定义a[0][1]=233,a[0][2]=2333,a[0][3]=23333,...给出n个数依次为a[1][0],a[2][0],
 * a[3][0]...a[n][0],且a[i][j]=a[i][j-1]+a[i-1][j](i>=1,j>=1),求出a[n][m].
 * 其中n<=10,m<=10^9.
 * 分析:
 * 由a[i][j]=a[i][j-1]+a[i-1][j](i>=1,j>=1),往前递推可得:
 * a[i][j]=a[0][j-1]+a[1][j-1]+..+a[i][j-1]+a[0][j].
 * 并且a[0][i]=a[0][i-1]*10+3,结合可构造一个(n+2)阶方阵
 * A=
 * 1 0  0 0 . . . 0 0
 * 1 10 0 0 . . . 0 0
 * 0 1  1 0 . . . 0 0
 * . .  . . . . . . .
 * 0 1  1 1 . . . 1 0
 * 0 1  1 1 . . . 1 1.
 * 使得:
 *      3           3
 *      a[i][1]     a[i+1][1]
 *      a[1][i]     a[1][i+1]
 * A *  a[2][i]  =  a[2][i+1]
 *      . . .       . . .
 *      a[n][i]     a[n][i+1]
 *然后运用矩阵快速幂即可.
 */
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const long long mod=(long long)(1e7+7);

struct Matrix{
    int row,col;
    long long data[15][15];
}ans,cur;

void Init(Matrix& x,int n)
{
    x.row=x.col=n+2;
    for(int i=1;i<=n+2;i++){
        for(int j=1;j<=n+2;j++){
            if(i==1){
                if(j==1) x.data[i][j]=1;
                else x.data[i][j]=0;
            }else if(i==2){
                if(j==1) x.data[i][j]=1;
                else if(j==2) x.data[i][j]=10;
                else x.data[i][j]=0;
            }else{
                if(j==1||j>i) x.data[i][j]=0;
                else x.data[i][j]=1;
            }
           //if(j==n+2) x.data[i][j]=1;
        }
    }
}

Matrix multiply(Matrix a,Matrix b)
{
    Matrix anss;
    anss.row=a.row;
    anss.col=b.col;
    memset(anss.data,0,sizeof(anss.data));
    for(int i=1;i<=anss.row;i++){
        for(int j=1;j<=anss.col;j++){
            for(int k=1;k<=a.col;k++){
                anss.data[i][j]+=a.data[i][k]*b.data[k][j];
                anss.data[i][j]%=mod;
            }
        }
    }
    return anss;
}

Matrix quick_power(Matrix a,long long m)
{
    Matrix anss,tmp=a;
    anss.row=a.row;
    anss.col=a.col;
    memset(anss.data,0,sizeof(anss.data));
    for(int i=1;i<=anss.row;i++)
        anss.data[i][i]=1;
    while(m)
    {
        if(m&1) anss=multiply(anss,tmp);
        tmp=multiply(tmp,tmp);
        m>>=1;
    }
    return anss;
}

void debug(Matrix x,int i)
{
    printf("debug case %d: row=%d col=%d\n",i,x.row,x.col);
    for(int i=1;i<=x.row;i++){
        for(int j=1;j<=x.col;j++){
            printf("%I64d ",x.data[i][j]);
        }
        printf("\n");
    }
}

int main()
{
    //freopen("Bin.txt","r",stdin);
    int n;
    long long m;
    while(~scanf("%d %I64d",&n,&m)){
        Init(ans,n);
        cur.row=n+2;
        cur.col=1;
        cur.data[1][1]=3;
        cur.data[2][1]=233;
        for(int i=1;i<=n;i++)
            scanf("%I64d",&cur.data[i+2][1]);
        //printf("*****************\n");
        //debug(ans,1);
        //debug(cur,2);
        ans=quick_power(ans,m);
        cur=multiply(ans,cur);
        //debug(ans,3);
        //debug(cur,4);
        //printf("*****************\n");
        printf("%I64d\n",(cur.data[n+2][1]+mod)%mod);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值