233 Matrix HDU - 5015(矩阵快速幂)

233 Matrix HDU - 5015

In our daily life we often use 233 to express our feelings. Actually, we may say 2333, 23333, or 233333 … in the same meaning. And here is the question: Suppose we have a matrix called 233 matrix. In the first line, it would be 233, 2333, 23333… (it means a 0,1 = 233,a 0,2 = 2333,a 0,3 = 23333…) Besides, in 233 matrix, we got a i,j = a i-1,j +a i,j-1( i,j ≠ 0). Now you have known a 1,0,a 2,0,…,a n,0, could you tell me a n,m in the 233 matrix?
Input
There are multiple test cases. Please process till EOF.

For each case, the first line contains two postive integers n,m(n ≤ 10,m ≤ 10 9). The second line contains n integers, a 1,0,a 2,0,…,a n,0(0 ≤ a i,0 < 2 31).
Output
For each case, output a n,m mod 10000007.
Sample Input
1 1
1
2 2
0 0
3 7
23 47 16
Sample Output
234
2799
72937
这里写图片描述
解题思路:由题意可得矩阵的第一列
0
a[1]

a[2]

a[3]

a[4]

为了凑233转化为

23

a[1]

a[2]

a[3]

a[4]

3

由 a i,j = a i-1,j +a i,j-1可以得到第二列

23*10+3

a[1]+23*10+3

a[2]+a[1]+23*10+3

a[3]+a[2]+a[1]+23*10+3

a[4]+a[3]+a[2]+a[1]+23*10+3

3

由此推得转移矩阵

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次方
那么最后一列就是A的m次方乘第一列。在求转移矩阵的时候使用快速幂的思想,最后求出来的结果是一个矩阵。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define N 15
const int mod=10000007;//因为数很大需要取模
int n;
int b[N];
struct Mat
{
    long long mat[N][N];
}a,ans;
Mat mul(Mat a,Mat b)
{
    int i,j,k;
    Mat c;
    memset(c.mat,0,sizeof(c.mat));
    for(i=0; i<=n+1; i++)
    {
        for(j=0; j<=n+1; j++)
        {
            c.mat[i][j]=0;
            for(k=0; k<=n+1; k++)
            {
                if(a.mat[i][k]&&b.mat[k][j])
                {
                    c.mat[i][j]+=a.mat[i][k]*b.mat[k][j];//矩阵乘法
                    c.mat[i][j]%=mod;
                }
            }
        }
    }
    return c;//返回乘完了之后的矩阵
}
void kuaisumi(int m)
{
    int i;
    memset(ans.mat,0,sizeof(ans.mat));
    for(i=0;i<=n+1;i++)
        ans.mat[i][i]=1;
    while(m)//使用快速幂的思想进行矩阵的m次方相乘
    {
        if(m&1)//就是m%2==0
            ans=mul(ans,a);
        m/=2;
        a=mul(a,a);
    }
}
void inti()
{
    int i,j;
    b[0]=23;//b数组就是第一列,最后与转移矩阵的m次方相乘得到anm
    b[n+1]=3;
    for(i=1; i<=n; i++)
        scanf("%d",&b[i]);
    memset(a.mat,0,sizeof(a.mat));
    for(i=0; i<=n; i++)
    {
        a.mat[i][0]=10;
        a.mat[i][n+1]=1;
    }
    a.mat[n+1][n+1]=1;
    for(i=1; i<n+1; i++)
    {
        for(j=1; j<=i; j++)
        {
            a.mat[i][j]=1;
        }
    }
}
int main()
{
    int i,m;
    while(~scanf("%d%d",&n,&m))
    {
        inti();
        kuaisumi(m);
        long long s=0;
        for(i=0;i<=n+1;i++)
            s=(s+(ans.mat[n][i]*b[i])%mod)%mod;
        printf("%lld\n",s);
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值