是小学数学题吗?

题目:

我还是从前那个少年,没有"亿"丝丝改变!

在家学习肯定很累吧???大学的题可太难了!!!好像回到小学呀QAQ~~。

忽然,你拿起了表弟的数学作业本,看到表弟竟然做错了,于是作为数学dalao的你想要在表弟面前秀一波操作。

题目的描述是这样的:先在已知A为 n×n 的矩阵,让你求 S = 2^{m-1}×A+2^{m-2}×A^2+……+2^{m-m}×A^m 

果然,你不到1s就在大脑中算出了答案S,并且S的每一个元素对 1e9+7 取模。

Input

第一行,包含两个正整数 n ,m ,分别代表矩阵A的大小和S中的项数。(1<=n<=30,1<=m<=1e9)

第二行到第 n+1 行,每行 n 个元素,相应地代表A中的元素 x 。(0<=x<=1e6)

Output

输出包括 n 行,每行 n 个元素,代表S中的每一个元素对 1e9+7 取模后的值。

Sample Input

1 2020
1

思路:

构造矩阵{A,1,

               0,2} ;

求此矩阵m+1次方,右上角即为答案矩阵+2^m*E,得到右上角矩阵减去2^m*E,即为答案矩阵。                 

代码:

#define _CRT_SECURE_NO_WARNINGS 
#include <iostream>
#include <queue>
#include<algorithm>
#include<cmath>
#include<map>
#include<unordered_set>
#include<string.h>
#include<string>
#include<cstring>
using namespace std;
const long long MX = 1e9 + 7;
long long  n, m;
typedef struct data
{
    long long  v[62][62];
}M;
M P;
M I;
M seek(M u, M o)
{
    M c;
    for (int i = 0; i < 2 * n; i++)
        for (int j = 0; j < 2 * n; j++)
        {
            c.v[i][j] = 0;
            for (int l = 0; l <2*n; l++)
            {
                u.v[i][l] = u.v[i][l] % MX;
                o.v[l][j] = o.v[l][j] % MX;
                c.v[i][j] += (u.v[i][l] * o.v[l][j]) % MX;
                c.v[i][j] = (c.v[i][j] % MX + MX) % MX;
            }
        }
    return c;
}
M quicksek(long long x)
{
    M G, F;
    G = I;
    F = P;
    while (x >= 1)
    {
        if (x & 1)
            G = seek(G, F);
        x = x >> 1;
        F = seek(F, F);
    }
    return G;
}
long long quacksek(long long x)
{
    long long b = 1,e=2;
    while (x)
    {
        if (x & 1)
            b = (b * e) % MX;
        x = x >> 1;
        e = (e * e) % MX;
    }
    return b;
}
int main()
{
    M a,q;
    cin >> n >> m;
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            cin >> P.v[i][j];
    for (int i = n; i < 2 * n; i++)
    {
        P.v[i - n][i] = 1;
        P.v[i][i] = 2;
    }
    for (int i = 0; i < 2 * n; i++)
        I.v[i][i] = 1;
    q=quicksek(m + 1);
    for (int i = 0; i < n; i++)
        for (int j = n; j < 2 * n; j++)
             a.v[i][j - n]=q.v[i][j];
     long long x=quacksek(m)%MX;
     for (int i = 0; i <n; i++)
         a.v[i][i] = ((a.v[i][i] - x) % MX+MX)%MX;
     for (int i = 0; i <n; i++)
     {
         for (int j = 0; j < n; j++)
         {  if(j!=n-1)
             cout << a.v[i][j] << " ";
            else
             cout <<a.v[i][j]<<endl;
         }
     }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值