矩阵快速幂-HDU5015

152 篇文章 0 订阅
16 篇文章 0 订阅

PS寻思一小时。构造半小时。代码半小时。无限长的DEBUG。

思路:

本来天真的找到规律。想斜线走规律的。结果突然发现233....3这也太坑了!

之后知道了可以构造矩阵快速幂的形式来AC。就开始了构造之旅。。

首先:2333这种形式。因为是个素数。必定无法用一个位置构造出来。那么我们可以拆成2330+3  230+3 23+3 类似的形式。

接下来就是规律的问题了。

拿第一列

233                                                 2333

233+a[1][0]                                  2333+a[1][1]

233+a[1][0]+a[2][0]                     2333+a[1][1]+a[2][1]

233+a[1][0]+a[2][0]+a[3][0]                .....

因为m很大。自然需要构造m的快速幂矩阵。  只要取得当前列,就可以依此来作为下一个标准进行矩阵乘法。

构造的base矩阵如下.

10    0   0    0 ... 1  //构造上个23333*10

        10    1   0    0 ....1

        10    1   1    0 ....1 

         10    1   1   1 ....1

0      0    0   0 ...1 // 补3


#include <iostream>
#include <stdio.h>
#include <cstring>
using namespace std;
typedef long long ll;
ll mod=10000007;
struct matrix
{
    ll arr[15][15];
}matrix_base,matrix_ans,temp;
int n,m;
int tt[15];
void init()
{
    memset(matrix_base.arr,0,sizeof(matrix_base.arr));
    matrix_base.arr[1][1]=10;
    matrix_base.arr[1][n+2]=1;
    for(int i=2;i<=n+1;i++)
    {
        matrix_base.arr[i][1]=10;
        for(int j=2;j<=i;j++)
        {
            matrix_base.arr[i][j]=1;
        }
        matrix_base.arr[i][n+2]=1;
    }
    matrix_base.arr[n+2][n+2]=1;
    memset(matrix_ans.arr,0,sizeof(matrix_ans.arr));
    matrix_ans.arr[1][1]=23;
    matrix_ans.arr[n+2][1]=3;
    for(int i=2;i<=n+1;i++)
        matrix_ans.arr[i][1]=tt[i-1];
}

matrix matrix_mulip(matrix a,matrix b)
{
    memset(temp.arr,0,sizeof(temp.arr));
    for(int i=1;i<=n+2;i++)
    {
        for(int j=1;j<=n+2;j++)
        {
            for(int k=1;k<=n+2;k++)
            {
                temp.arr[i][j]=(temp.arr[i][j]+b.arr[i][k]*a.arr[k][j])%mod;
            }
        }
    }
    return temp;
}
void matrix_pow( int  x)
{
    while(x)
    {
        if(x%2)
        {
            matrix_ans=matrix_mulip(matrix_ans,matrix_base);
        }
        matrix_base=matrix_mulip(matrix_base,matrix_base);
        x=x/2;
    }
}

int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        for(int i=1;i<=n;i++)
            cin>>tt[i];
        init();
        matrix_pow( m);
        cout<<matrix_ans.arr[n+1][1]%mod<<endl;

    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值