寄寄寄寄寄寄寄寄寄寄寄寄寄寄寄寄寄|

TLE_Automation

园龄:2年9个月粉丝:19关注:23

P8110 [Cnoi2021] 矩阵题解

前言

这篇题解可能有点啰嗦,个人还是觉得比较通俗易懂的。

这道题可能会用到点矩阵的知识,没学过矩阵的可以参考我的这篇博客:

【矩阵浅谈】

题意:

给你两个序列 {an},{bn}

告诉你一个矩阵 A 是满足 Ai,j=ai×bj 的。

Ak 中所以元素的和。

思路:

看到数据范围 n105 和题目背景中的:

Rumia 喜欢矩阵快速幂,而 Cirno 觉得这是平凡的。

能推出这题不是矩阵快速幂的板子,而是一个考虑两个数组对于这个矩阵的贡献的问题。

我们从样例 1 入手:

3 0
1 2 3
4 5 6

我们可以得到 A 矩阵为:

{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}

发现 2 个序列中每个点都有 3 处贡献。

我们再考虑这个式子的实际意义:

就是 a 序列中每个点都对应着 b 序列中的每一个点。

所以说 a 序列和 b 序列中的每个点都会对原矩阵做出 n 次贡献。

这个时候我们只考虑了序列对于矩阵 A 的贡献,而不知道对于 Ak 的贡献。

我们再来考虑矩阵乘法的式子的意义:

Ci,j=r=1bAi,r×Br,j

而这里 A 矩阵和 B 矩阵相同。

所以可以转化为:

Ci,j=r=1bAi,r×Ar,j

比如说:
矩阵的第一行:
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])。

从这个式子我们可以看出一个结论:

一个矩阵自乘后矩阵元素的总和,就是他的第 n 行乘第 n 列的和。

我们再根据之前得出的结论:

这个矩阵中 a 序列和 b 序列中的每个点都会对原矩阵做出 n 次贡献。

如果我们要算出矩阵 A 后在求,算矩阵 A 的复杂度为 O(n2),因为对于每个 a 序列里的数都要扫一遍 b 序列,所以这题我们要直接考虑 a 序列和 b 序列对于矩阵的贡献。

根据这两个结论推得:

ans=ai×bi×(ai×bi)k1

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 中国大陆许可协议进行许可。

posted @   TLE_Automation  阅读(31)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起