问题描述
试题编号: | 202305-2 |
试题名称: | 矩阵运算 |
时间限制: | 5.0s |
内存限制: | 512.0MB |
问题描述: | 题目背景Softmax(Q×KTd)×V 是 Transformer 中注意力模块的核心算式,其中 Q、K 和 V 均是 n 行 d 列的矩阵,KT 表示矩阵 K 的转置,× 表示矩阵乘法。 问题描述为了方便计算,顿顿同学将 Softmax 简化为了点乘一个大小为 n 的一维向量 W: 现给出矩阵 Q、K 和 V 和向量 W,试计算顿顿按简化的算式计算的结果。 输入格式从标准输入读入数据。 输入的第一行包含空格分隔的两个正整数 n 和 d,表示矩阵的大小。 接下来依次输入矩阵 Q、K 和 V。每个矩阵输入 n 行,每行包含空格分隔的 d 个整数,其中第 i 行的第 j 个数对应矩阵的第 i 行、第 j 列。 最后一行输入 n 个整数,表示向量 W。 输出格式输出到标准输出中。 输出共 n 行,每行包含空格分隔的 d 个整数,表示计算的结果。 样例输入 Data 样例输出 Data 子任务70 的测试数据满足:n≤100 且 d≤10;输入矩阵、向量中的元素均为整数,且绝对值均不超过 30。 全部的测试数据满足:n≤104 且 d≤20;输入矩阵、向量中的元素均为整数,且绝对值均不超过 1000。 提示请谨慎评估矩阵乘法运算后的数值范围,并使用适当数据类型存储矩阵中的整数。 |
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
long long a[1000][100],b[1000][100],c[1000][100],d[1000],e[1000][100],f[1000][100],g[1000][100];
int main()
{
long long i,j,k,m,n,p;
cin>>n>>m;
for(i=1;i<=3;i++)
{
for(j=1;j<=n;j++)
{
for(k=1;k<=m;k++)
{
if(i==1){cin>>a[j][k];}
else if(i==2){cin>>b[j][k];}
else {cin>>c[j][k];}
}
}
}//输入数据Q,K,V;
for(i=1;i<=n;i++)
{
cin>>d[i];
}//输入向量M;
for(i=1;i<=m;i++)
{
for(j=1;j<=n;j++)
{
e[i][j]=b[j][i];
}
}
//转置K矩阵;
for(j=1;j<=n;j++)
{
for(k=1;k<=n;k++)
{
f[j][k]=0;
for(i=1;i<=m;i++)
{
f[j][k]+=a[j][i]*e[i][k];
}
}
}
//Q*KT;
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
f[i][j]=f[i][j]*d[i];
}
}
//m*f;
for(j=1;j<=n;j++)
{
for(k=1;k<=m;k++)
{
g[j][k]=0;
for(i=1;i<=n;i++)
{
g[j][k]+=f[j][i]*c[i][k];
}
}
}
//最后一步矩阵的乘法
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
if(j!=m)cout<<g[i][j]<<" ";
else cout<<g[i][j]<<endl;
}
}
//输出结果
return 0;
}
1.本题能力有限只能A一半 得70 原因是运行超时,但结果没问题。常规不动脑敲就只能这样。还需要优化,省时。
2.本题要考虑数据过大的情况,矩阵相乘是会出现longlong。就直接longlong定义,内存还是没有卡的。
3.这是矩阵基本运算,逆、转置、乘、加等