POJ 3233
描述
Given a n × n matrix A and a positive integer k, find the sum S=A+A2+A3+…+Ak.S=A+A2+A3+…+Ak.
输入
The input contains exactly one test case. The first line of input contains three positive integers n (n ≤ 30), k (k ≤ 10e9) and m (m < 104). Then follow n lines each containing n nonnegative integers below 32768, giving A’s elements in row-major order.
输出
Output the elements of S modulo m in the same way as A is given.
样例输入
2 2 4
0 1
1 1
样例输出
1 2
2 3
思路
起初我直接矩阵快速幂,然后把结果相加,可是TLE了,然后去百度看看别人的思路,找到一个神奇的公式。
B=[AE0E]
Bk+1=[Ak+1E+A+A2+A3+…+Ak0E]
有了这个公式之后,写了个分块矩阵就好,顺便重构了一下我那惨不忍睹的矩阵快速幂模版。
虽然被大佬嫌弃代码啰嗦,但还是放上来吧。
代码
#include <cstdio>
#include<cstring>
#define ll long long
#define maxn 32
using namespace std;
int n, k, mod;
struct Mat
{
ll f[maxn][maxn];
void cls(){memset(f, 0, sizeof(f));}//全部置为0
Mat() {cls();}
void myprint(int n)//输出n阶顺序主子式
{
for(int i = 0; i < n; i++)
{
for(int j = 0; j < n; j++)
printf("%d ", f[i][j] % mod);
printf("\n");
}
}
friend Mat operator + (Mat a, Mat b)
{
Mat res;
for(int i = 0; i < maxn; i++)
for(int j = 0; j < maxn; j++)
res.f[i][j] = a.f[i][j] + b.f[i][j];
return res;
}
friend Mat operator - (Mat a, Mat b)
{
Mat res;
for(int i = 0; i < maxn; i++)
for(int j = 0; j < maxn; j++)
{
res.f[i][j] = a.f[i][j] - b.f[i][j];
while(res.f[i][j] < 0) res.f[i][j] += mod;
}
return res;
}
friend Mat operator * (Mat a, Mat b)
{
Mat res;
for(int i = 0; i < maxn; i++)for(int j = 0; j < maxn; j++)
for(int k = 0; k < maxn; k++)
(res.f[i][j] += a.f[i][k] * b.f[k][j]) %= mod;
return res;
}
} E, I;
struct MatDiv
{
Mat s[2][2];
void set(Mat x1, Mat x2, Mat x3, Mat x4)
{
s[0][0] = x1; s[0][1] = x2;
s[1][0] = x3; s[1][1] = x4;
}
friend MatDiv operator * (MatDiv a, MatDiv b)
{
MatDiv res;
for(int i = 0; i < 2; i++) for(int j = 0; j < 2;j++)
for(int k = 0; k < 2; k++)
res.s[i][j] = a.s[i][k] * b.s[k][j] + res.s[i][j];
return res;
}
};
MatDiv quick_pow(MatDiv a)
{
MatDiv ans;
ans.set(E, I, E, I);
ll b = k;
while(b != 0)
{
if(b & 1) ans = ans * a;
b >>= 1;
a = a * a;
}
return ans;
}
int main()
{
for(int i = 0; i < maxn; i++)
E.f[i][i] = 1;
while(~scanf("%d %d %d", &n, &k, &mod))
{
Mat A; k++;
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
scanf("%d", &A.f[i][j]);
MatDiv B; B.set(A, E, I, E);
B = quick_pow(B);
A = B.s[0][1] - E;
A.myprint(n);
}
return 0;
}
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
· 互联网不景气了那就玩玩嵌入式吧,用纯.NET开发并制作一个智能桌面机器人(四):结合BotSharp
· Vite CVE-2025-30208 安全漏洞
· 《HelloGitHub》第 108 期
· MQ 如何保证数据一致性?
· 一个基于 .NET 开源免费的异地组网和内网穿透工具