题目:
我还是从前那个少年,没有"亿"丝丝改变! 在家学习肯定很累吧???大学的题可太难了!!!好像回到小学呀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;
}