P8110 [Cnoi2021] 矩阵题解
前言
这篇题解可能有点啰嗦,个人还是觉得比较通俗易懂的。
这道题可能会用到点矩阵的知识,没学过矩阵的可以参考我的这篇博客:
题意:
给你两个序列 。
告诉你一个矩阵 是满足 的。
求 中所以元素的和。
思路:
看到数据范围 和题目背景中的:
Rumia
喜欢矩阵快速幂,而Cirno
觉得这是平凡的。
能推出这题不是矩阵快速幂的板子,而是一个考虑两个数组对于这个矩阵的贡献的问题。
我们从样例 入手:
3 0 1 2 3 4 5 6
我们可以得到 矩阵为:
{4 5 6} = {1 × 4, 1 × 5, 1 × 6} {8 10 12} = {2 × 4, 2 × 5, 2 × 6} {12 15 18} = {3 × 4, 3 × 5, 3 × 6}
发现 个序列中每个点都有 处贡献。
我们再考虑这个式子的实际意义:
就是 序列中每个点都对应着 序列中的每一个点。
所以说 序列和 序列中的每个点都会对原矩阵做出 次贡献。
这个时候我们只考虑了序列对于矩阵 的贡献,而不知道对于 的贡献。
我们再来考虑矩阵乘法的式子的意义:
而这里 矩阵和 矩阵相同。
所以可以转化为:
比如说: 矩阵的第一行: c[1][1] = a[1][1] × a[1][1] + a[1][2] × a[2][1] + a[1][3] × a[3][1]; c[1][2] = a[1][1] × a[1][2] + a[1][2] × a[2][2] + a[1][3] × a[3][2]; c[1][3] = a[1][1] × a[1][3] + a[1][2] × a[2][3] + a[1][3] × a[3][3]; 我们对于矩阵的第一行求和: sum1 = c[1][1] + c[1][2] + c[1][3] = a[1][1] × (a[1][1] + a[1][2] + a[1][3]) + a[1][2] × (a[2][1] + a[2][2] + a[2][3]) + a[1][3] × (a[3][1] + a[3][2] + a[3][3])。
可能光看第一行你还不知道有什么规律,我再把第二行都列出来:
矩阵的第二行: c[2][1] = a[2][1] × a[1][1] + a[2][2] × a[2][1] + a[2][3] × a[3][1]; c[2][2] = a[2][1] × a[1][2] + a[2][2] × a[2][2] + a[2][3] × a[3][2]; c[2][3] = a[2][1] × a[1][3] + a[2][2] × a[2][3] + a[2][3] × a[3][3]; sum2 = c[2][1] + c[2][2] + c[2][3] = a[2][1] × (a[1][1] + a[1][2] + a[1][3]) + a[2][2] × (a[2][1] + a[2][2] + a[2][3]) + a[2][3] × (a[3][1] + a[3][2] + a[3][3]);
第三行:
矩阵的第三行: c[3][1] = a[3][1] × a[1][1] + a[3][2] × a[2][1] + a[3][3] × a[3][1]; c[3][2] = a[3][1] × a[1][2] + a[3][2] × a[2][2] + a[3][3] × a[3][2]; c[3][3] = a[3][1] × a[1][3] + a[3][2] × a[2][3] + a[3][3] × a[3][3]; sum2 = c[3][1] + c[3][2] + c[3][3] = a[3][1] × (a[1][1] + a[1][2] + a[1][3]) + a[3][2] × (a[2][1] + a[2][2] + a[2][3]) + a[3][3] × (a[3][1] + a[3][2] + a[3][3]);
根据上述三行可知:
矩阵的元素总和为: Sum = sum1 +sum2 + sum3 = (a[1][1] + a[1][2] + a[1][3]) × (a[1][1] + a[2][1] + a[3][1]) + (a[2][1] + a[2][2] + a[2][3]) × (a[1][2] + a[2][2] + a[3][2]) + (a[3][1] + a[3][2] + a[3][3]) × (a[1][3] + a[2][3] + a[3][3])。
从这个式子我们可以看出一个结论:
一个矩阵自乘后矩阵元素的总和,就是他的第 行乘第 列的和。
我们再根据之前得出的结论:
这个矩阵中 序列和 序列中的每个点都会对原矩阵做出 次贡献。
如果我们要算出矩阵 后在求,算矩阵 的复杂度为 ,因为对于每个 序列里的数都要扫一遍 序列,所以这题我们要直接考虑 序列和 序列对于矩阵的贡献。
根据这两个结论推得:
AC code:
/* work by: TLE_Automation Time: O(轻轻松松过) knowledge: 垃圾算法 */ #include<bits/stdc++.h> #define int long long #define orz cout << "szt lps fjh AK IOI"; using namespace std; const int INF = 1e9 + 7; const int mod = 998244353; const int maxn = 2e5 + 10; const int MAXN = 3e3 + 10; inline int read() { int s = 0, w = 1; char ch = getchar(); while (!isdigit(ch)) {if(ch == '-') {w = -1;}ch = getchar();} while (isdigit(ch)) {s = (s << 1) + (s << 3) + (ch ^ 48);ch = getchar();} return s * w; } inline void print(int x) { if (x < 0 ) putchar('-'), x = -x; if (x > 9 ) print(x / 10); putchar(x % 10 + '0'); } int n, k, a[maxn], b[maxn]; int ksm(int a, int b) { int res = 1, base = a; while(b) { if(b & 1) res = (res * base) % mod; base = (base * base) % mod, b >>= 1; }return res; } int ans = 1; int sum = 0; int ans1 = 0, ans2 = 0; signed main() { n = read(), k = read(); if(k == 0) return print(n), 0; for(int i = 1; i <= n; i++) a[i] = read(), ans1 = (ans1 + a[i]) % mod; for(int i = 1; i <= n; i++) b[i] = read(), ans2 = (ans2 + b[i]) % mod; for(int i = 1; i <= n; i++) { sum = (sum + a[i] * b[i]) % mod; } ans1 %= mod, ans2 %= mod; ans = (((ans1 % mod * ans2 % mod) % mod) * ksm(sum, k - 1) % mod + mod) %mod; print(ans % mod); }
本文作者:TLE_Automation
本文链接:https://www.cnblogs.com/tttttttle/p/16293603.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!