233 Matrix(矩阵快速幂)

这篇博客介绍了如何解决一个涉及矩阵递推的问题,其中矩阵元素由第一行和第一列的值通过递推公式a[i][j] = a[i-1][j]+a[i][j-1]确定。当需要计算第n行第m列的值时,通过矩阵快速幂的方法可以高效地处理,避免直接递推带来的巨大计算量。文章详细解释了如何构造矩阵,并给出了具体的矩阵变换示例和代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

233 Matrix

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1471    Accepted Submission(s): 863


Problem Description
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
Hint
 

Source
 


题意:

给你一个矩阵的第一行和第一列,让你求第n行第m列的值。其中矩阵中元素有递推式a[i][j] = a[i-1][j]+a[i][j-1]。其中第一行为0,233,2333,23333...,第一列为0,x1,x2,x3...,xi在输入中给出。n<=10,m<=10^9

分析:

一开始我还想通过递推关系找规律呢==,后来发现不是很好找,即使找到相应的东西也需要求10^9个元素的和。。。想想可以用矩阵快速幂解决,对于这种有着递推关系且数量较大的递推式来说,但始终想不到如何构造矩阵。。。后来看题解才知道,原来可以一列一列往右推构成递推关系。如果去掉第一行,我们很容易构造矩阵来将第一列推到第二列,而对于233到2333这些我们可以*10+3递推到,然后如果要合一起的话这里需要再增加一行才能实现233推到2333。首先第一行第一个数可以改为23这样更好满足*10+3的关系且并不会影响最终结果,然后我们再增加n+1这行,全是3,这样就很容易利用矩阵从一列推到另一列了。例如n=3,m=3的情况,可以构造矩阵:


233                         10 0 0 0 1       23
x1+233                   10 1 0 0 1       x1
x1+x2+233      =     10 1 1 0 1   *   x2
x1+x2+x3+233       10 1 1 1 1       x3
3                             0  0 0 0 0       3


code:

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<string>
#include<queue>
#include<algorithm>
using namespace std;
const int mod = 1e7+7;
const int N = 1e5+10;
typedef long long ll;
#define INF 1<<30
int n, m;
struct Mat
{
    ll mat[15][15];
};

Mat operator * (Mat a, Mat b)
{
    Mat c;
    memset(c.mat, 0, sizeof(c.mat));
    for(int k=0; k<n+2; k++)
        for(int i=0; i<n+2; i++)
            for(int j=0; j<n+2; j++)
                c.mat[i][j] = (c.mat[i][j]+a.mat[i][k]*b.mat[k][j])%mod;
    return c;
}

int main()
{

    while(~scanf("%d%d", &n,&m))
    {
        Mat res, a;
        for(int i=0; i<n+2; i++)
            for(int j=0; j<n+2; j++)
                res.mat[i][j] = (i==j);
        for(int i=0; i<n+2; i++)
        {
            for(int j=0; j<n+2; j++)
            {
                if(j == 0 && i != n+1) a.mat[i][j] = 10;
                else if((i >= j && i != n+1) || j == n+1) a.mat[i][j] = 1;
                else a.mat[i][j] = 0;
            }
        }
        for(; m>0; m>>=1)
        {
            if(m & 1) res = res*a;
            a = a*a;
        }
        ll x, ans = 23*res.mat[n][0];
        for(int i=1; i<=n; i++)
        {
            scanf("%lld", &x);
            ans = (ans+x*res.mat[n][i]%mod)%mod;
        }
        ans = (ans+3*res.mat[n][n+1]%mod)%mod;
        printf("%lld\n", ans);
    }
    return 0;
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值