『题解』Luogu B3615 测测你的矩阵乘法
题目大意
给定两个大小为 \(512 \times 512\),每个元素均为整数,值域为 \([0,1024)\) 的矩阵 \(a,b\),定义为
其中 \(i,j \in [0,512)\)。
请计算 \(c=a \times b\)。
输出 \(512\) 行,分别是 \(c\) 每行的异或和。
思路
矩阵乘法
先来介绍下什么是矩阵乘法。
例如有两个 \(3 \times 3\) 的矩阵 \(a,b\),如题目所述。
\(a\) 矩阵如下:
\( \begin{matrix} &\begin{matrix} 1&2&3\\ \end{matrix}\\ \begin{matrix} 1\\2\\3 \end{matrix} &\begin{bmatrix} 1&2&3\\ 4&5&6\\ 7&8&9\\ \end{bmatrix} \end{matrix} \)
\(b\) 矩阵如下:
\( \begin{matrix} &\begin{matrix} 1&2&3\\ \end{matrix}\\ \begin{matrix} 1\\2\\3 \end{matrix} &\begin{bmatrix} 9&8&7\\ 6&5&4\\ 3&2&1\\ \end{bmatrix} \end{matrix} \)
\(c_{i,j}\) 就是 \(a\) 的第 \(i\) 行的各个元素与 \(b\) 的第 \(j\) 列的各个元素相乘的和。
如果要求 \(c_{2,2}\),那么就是 \(a\) 矩阵的
\( \begin{matrix} &\begin{matrix} 1&2&3\\ \end{matrix}\\ \begin{matrix} 1\\2\\3 \end{matrix} &\begin{bmatrix} 1&2&3\\ \color{red}4&\color{gold}5&\color{lightblue}6\\ 7&8&9\\ \end{bmatrix} \end{matrix} \)
分别与 \(b\) 矩阵的
\( \begin{matrix} &\begin{matrix} 1&2&3\\ \end{matrix}\\ \begin{matrix} 1\\2\\3 \end{matrix} &\begin{bmatrix} 9&\color{red}8&7\\ 6&\color{gold}5&4\\ 3&\color{lightblue}2&1\\ \end{bmatrix} \end{matrix} \)
相乘后累加的和。
矩阵中相同颜色的值相乘,分别为 \(\color{red}{32}\color{black},\color{gold}{25}\color{black},\color{lightblue}{12}\)。这三个值相加的结果 \(69\) 就是 \(c_{2,2}\) 的值了。
题目中给出的矩阵是正方形矩阵,所以用一个 \(n\) 来代表边长。
那么,整个 \(c\) 矩阵就可以用下面的代码求出:
void multiply(){
for(int i=1; i<=n; i++){ // n 为矩阵的边长
for(int j=1; j<=n; j++){ // 枚举各个数的位置
for(int k=1; k<=n; k++){ // 循环行列
c[i][j]+=a[i][k]*b[k][j]; // 执行累加
}
}
}
}
本题
本题也和上面的例子相似,只不过初值不同。
\(a_{i,j}=(i \or j)+j\\ b_{i,j}=(i \and j)+i\)
但是注意,下标从 \(0\) 开始,对于我这种喜欢从 \(1\) 开始循环的 OIer 来说,真是个悲剧啊...
所以,赋初值的时候,值要用 \(i-1\) 和 \(j-1\) 来求。
求出 \(a,b\) 矩阵的代码如下:
for(int i=1; i<=n; i++){
for(int j=1; j<=n; j++){
int x=i-1,y=j-1; // 存储 i-1 和 j-1
a[i][j]=(x|y)+y;
b[i][j]=(x&y)+x; // 注意下标不变
}
}
对于输出,代码题目中也给出了:
for(int i=1; i<=n; i++,sum=0){ // 记得给 sum 赋初值 0
for(int j=1; j<=n; j++){
sum^=c[i][j]; // 计算单行异或和
}
cout << sum << endl;
}
再弄出本题的 AC 代码也不难。
为了混出来个最优解,我还弄了一份打表代码,我们可以弄一个字符串,存储输出的字符串。那个字符串是用上面的代码输出出来的,就把输出时的 endl
换成 "\\n"
,这样就成了一个标准的答案,复制到字符串里,一交,就过了。显然快了不少。
于是,交了一发,喜提 \(30ms\)!然后我又改成了 C 语言版本,交了一发,喜提 \(29ms\)!
目前是最优解榜一QwQ。
看来还真混到最优解了诶。
代码
普通代码
#include <iostream>
using namespace std;
const int n=512,N=n+5; // n 为计算用的边长,N 为数组长度
int a[N][N],b[N][N],c[N][N],sum;
void multiply(){
for(int i=1; i<=n; i++){ // n 为矩阵的边长
for(int j=1; j<=n; j++){ // 枚举各个数的位置
for(int k=1; k<=n; k++){ // 循环行列
c[i][j]+=a[i][k]*b[k][j]; // 执行累加
}
}
}
}
int main(){
for(int i=1; i<=n; i++){
for(int j=1; j<=n; j++){
int x=i-1,y=j-1; // 存储 i-1 和 j-1
a[i][j]=(x|y)+y;
b[i][j]=(x&y)+x; // 注意下标不变
}
}
multiply();
for(int i=1; i<=n; i++,sum=0){
for(int j=1; j<=n; j++){
sum^=c[i][j];
}
cout << sum << endl;
}
return 0;
}
打表代码
C 版(\(29ms\))
#include <stdio.h>
char s[114514]="8126464\n14942208\n33554432\n58916864\n4325376\n60817408\n34078720\n1114112\n3145728\n36306944\n40894464\n59572224\n49152000\n29491200\n14680064\n51970048\n54263808\n11665408\n4194304\n49610752\n19267584\n1179648\n50855936\n34537472\n25952256\n10878976\n25165824\n38862848\n11141120\n8912896\n18874368\n45154304\n17825792\n47972352\n4194304\n19202048\n57278464\n917504\n36175872\n26804224\n55574528\n38928384\n27262976\n30212096\n49676288\n35389440\n7864320\n49872896\n12845056\n14942208\n48234496\n14876672\n44695552\n34734080\n28835840\n27066368\n64749568\n16515072\n62914560\n35192832\n10092544\n2621440\n28835840\n16842752\n10485760\n25165824\n0\n36241408\n62259200\n6553600\n64487424\n63897600\n5505024\n262144000\n212860928\n42008576\n258867200\n2490368\n46661632\n201916416\n240648192\n5898240\n201326592\n212271104\n43646976\n244187136\n256376832\n63897600\n230162432\n243531776\n19922944\n232849408\n220594176\n10878976\n264765440\n204406784\n244318208\n247463936\n33554432\n48168960\n244711424\n2359296\n15728640\n216465408\n65798144\n60686336\n231735296\n24969216\n27656192\n259915776\n41418752\n41877504\n209453056\n217448448\n31457280\n211877888\n266207232\n59899904\n233308160\n240451584\n61603840\n26214400\n225443840\n35454976\n53084160\n54657024\n267911168\n24707072\n28573696\n47710208\n251658240\n26804224\n64618496\n207355904\n23068672\n61931520\n263454720\n232783872\n46137344\n261685248\n238944256\n23592960\n211288064\n210698240\n48758784\n10354688\n247463936\n13828096\n13500416\n228065280\n216530944\n42532864\n246153216\n243138560\n49283072\n60096512\n29753344\n35520512\n266338304\n11862016\n7864320\n50724864\n222298112\n37945344\n42860544\n268173312\n5242880\n24838144\n203161600\n241041408\n45088768\n58130432\n262799360\n14417920\n524288\n205717504\n201588736\n38535168\n37748736\n206897152\n249167872\n10092544\n264241152\n219217920\n13893632\n39714816\n224395264\n202309632\n22413312\n267780096\n204996608\n20643840\n210239488\n7864320\n25165824\n244252672\n237109248\n42467328\n66584576\n227737600\n261095424\n35651584\n239075328\n226295808\n21364736\n56492032\n208142336\n207814656\n21233664\n57540608\n224395264\n53280768\n52559872\n254017536\n264241152\n19857408\n115081216\n230555648\n36700160\n132317184\n210370560\n193200128\n2621440\n43581440\n3145728\n72613888\n46137344\n122880000\n173932544\n228851712\n114819072\n59179008\n214958080\n143261696\n1048576\n91815936\n261750784\n25296896\n88080384\n216727552\n268173312\n73531392\n48234496\n146604032\n235012096\n33947648\n112721920\n246349824\n186122240\n118226944\n14680064\n171507712\n224526336\n31588352\n87031808\n226557952\n65011712\n3276800\n33554432\n15269888\n20316160\n18612224\n46661632\n34275328\n66322432\n27262976\n224395264\n240713728\n2752512\n54657024\n233832448\n208207872\n55836672\n17301504\n262144000\n245039104\n21626880\n38010880\n208142336\n202440704\n18087936\n58327040\n252706816\n231276544\n30539776\n26476544\n212860928\n237961216\n247463936\n203948032\n46137344\n59047936\n237895680\n262799360\n15204352\n253427712\n243007488\n44826624\n40894464\n56033280\n265945088\n235405312\n15728640\n22216704\n261619712\n227934208\n67108864\n81330176\n255721472\n147324928\n36700160\n5963776\n161218560\n222429184\n91226112\n120520704\n219283456\n184942592\n14155776\n61014016\n156762112\n58720256\n67108864\n134414336\n227672064\n90963968\n19398656\n220266496\n188481536\n19398656\n17825792\n186318848\n258080768\n12189696\n79691776\n41222144\n120061952\n138412032\n220200960\n143196160\n123600896\n64356352\n195035136\n249364480\n45350912\n68812800\n256901120\n264830976\n113115136\n30539776\n178782208\n145424384\n174850048\n16777216\n29360128\n194576384\n251789312\n4718592\n90701824\n226951168\n245891072\n84279296\n66060288\n244776960\n152436736\n231473152\n57671680\n110821376\n265814016\n224657408\n127926272\n21823488\n58851328\n178782208\n261619712\n19857408\n94109696\n250871808\n238026752\n95617024\n35258368\n9175040\n159907840\n212140032\n206831616\n172621824\n0\n119078912\n196739072\n267517952\n115343360\n92733440\n215482368\n156368896\n137363456\n63111168\n74842112\n145096704\n241696768\n71368704\n90963968\n19005440\n230686720\n179503104\n22937600\n29753344\n168296448\n205324288\n26214400\n126484480\n44040192\n267190272\n152698880\n34734080\n56098816\n139132928\n177995776\n241958912\n117440512\n74252288\n64618496\n147062784\n156762112\n34144256\n70516736\n160563200\n254803968\n70713344\n91881472\n18219008\n205520896\n231538688\n44040192\n2490368\n16777216\n233111552\n256507904\n24641536\n92274688\n224198656\n246939648\n133300224\n63963136\n35192832\n154271744\n157286400\n47710208\n80150528\n262406144\n184811520\n33554432\n25231360\n118882304\n228458496\n233308160\n126812160\n130547712\n48496640\n85983232\n109117440\n7995392\n71565312\n94371840\n2293760\n15728640\n86769664\n69206016\n7143424\n117309440\n75759616\n40370176\n102170624\n120324096\n212598784\n204472320\n138084352\n20840448\n49545216\n181927936\n166789120\n159645696\n239730688\n218103808\n87621632\n112852992\n260308992\n174587904\n71892992\n23330816\n20578304\n141557760\n236912640\n33161216\n125698048\n131596288\n237043712\n267649024\n161611776\n109051904\n15007744\n156106752\n143130624\n239075328\n21823488\n133169152\n261881856\n264241152\n143458304\n121765888\n29097984\n146800640\n148570112\n";
int main(){
puts(s);
return 0;
}
C++ 版(\(30ms\))
#include <iostream>
using namespace std;
string s="8126464\n14942208\n33554432\n58916864\n4325376\n60817408\n34078720\n1114112\n3145728\n36306944\n40894464\n59572224\n49152000\n29491200\n14680064\n51970048\n54263808\n11665408\n4194304\n49610752\n19267584\n1179648\n50855936\n34537472\n25952256\n10878976\n25165824\n38862848\n11141120\n8912896\n18874368\n45154304\n17825792\n47972352\n4194304\n19202048\n57278464\n917504\n36175872\n26804224\n55574528\n38928384\n27262976\n30212096\n49676288\n35389440\n7864320\n49872896\n12845056\n14942208\n48234496\n14876672\n44695552\n34734080\n28835840\n27066368\n64749568\n16515072\n62914560\n35192832\n10092544\n2621440\n28835840\n16842752\n10485760\n25165824\n0\n36241408\n62259200\n6553600\n64487424\n63897600\n5505024\n262144000\n212860928\n42008576\n258867200\n2490368\n46661632\n201916416\n240648192\n5898240\n201326592\n212271104\n43646976\n244187136\n256376832\n63897600\n230162432\n243531776\n19922944\n232849408\n220594176\n10878976\n264765440\n204406784\n244318208\n247463936\n33554432\n48168960\n244711424\n2359296\n15728640\n216465408\n65798144\n60686336\n231735296\n24969216\n27656192\n259915776\n41418752\n41877504\n209453056\n217448448\n31457280\n211877888\n266207232\n59899904\n233308160\n240451584\n61603840\n26214400\n225443840\n35454976\n53084160\n54657024\n267911168\n24707072\n28573696\n47710208\n251658240\n26804224\n64618496\n207355904\n23068672\n61931520\n263454720\n232783872\n46137344\n261685248\n238944256\n23592960\n211288064\n210698240\n48758784\n10354688\n247463936\n13828096\n13500416\n228065280\n216530944\n42532864\n246153216\n243138560\n49283072\n60096512\n29753344\n35520512\n266338304\n11862016\n7864320\n50724864\n222298112\n37945344\n42860544\n268173312\n5242880\n24838144\n203161600\n241041408\n45088768\n58130432\n262799360\n14417920\n524288\n205717504\n201588736\n38535168\n37748736\n206897152\n249167872\n10092544\n264241152\n219217920\n13893632\n39714816\n224395264\n202309632\n22413312\n267780096\n204996608\n20643840\n210239488\n7864320\n25165824\n244252672\n237109248\n42467328\n66584576\n227737600\n261095424\n35651584\n239075328\n226295808\n21364736\n56492032\n208142336\n207814656\n21233664\n57540608\n224395264\n53280768\n52559872\n254017536\n264241152\n19857408\n115081216\n230555648\n36700160\n132317184\n210370560\n193200128\n2621440\n43581440\n3145728\n72613888\n46137344\n122880000\n173932544\n228851712\n114819072\n59179008\n214958080\n143261696\n1048576\n91815936\n261750784\n25296896\n88080384\n216727552\n268173312\n73531392\n48234496\n146604032\n235012096\n33947648\n112721920\n246349824\n186122240\n118226944\n14680064\n171507712\n224526336\n31588352\n87031808\n226557952\n65011712\n3276800\n33554432\n15269888\n20316160\n18612224\n46661632\n34275328\n66322432\n27262976\n224395264\n240713728\n2752512\n54657024\n233832448\n208207872\n55836672\n17301504\n262144000\n245039104\n21626880\n38010880\n208142336\n202440704\n18087936\n58327040\n252706816\n231276544\n30539776\n26476544\n212860928\n237961216\n247463936\n203948032\n46137344\n59047936\n237895680\n262799360\n15204352\n253427712\n243007488\n44826624\n40894464\n56033280\n265945088\n235405312\n15728640\n22216704\n261619712\n227934208\n67108864\n81330176\n255721472\n147324928\n36700160\n5963776\n161218560\n222429184\n91226112\n120520704\n219283456\n184942592\n14155776\n61014016\n156762112\n58720256\n67108864\n134414336\n227672064\n90963968\n19398656\n220266496\n188481536\n19398656\n17825792\n186318848\n258080768\n12189696\n79691776\n41222144\n120061952\n138412032\n220200960\n143196160\n123600896\n64356352\n195035136\n249364480\n45350912\n68812800\n256901120\n264830976\n113115136\n30539776\n178782208\n145424384\n174850048\n16777216\n29360128\n194576384\n251789312\n4718592\n90701824\n226951168\n245891072\n84279296\n66060288\n244776960\n152436736\n231473152\n57671680\n110821376\n265814016\n224657408\n127926272\n21823488\n58851328\n178782208\n261619712\n19857408\n94109696\n250871808\n238026752\n95617024\n35258368\n9175040\n159907840\n212140032\n206831616\n172621824\n0\n119078912\n196739072\n267517952\n115343360\n92733440\n215482368\n156368896\n137363456\n63111168\n74842112\n145096704\n241696768\n71368704\n90963968\n19005440\n230686720\n179503104\n22937600\n29753344\n168296448\n205324288\n26214400\n126484480\n44040192\n267190272\n152698880\n34734080\n56098816\n139132928\n177995776\n241958912\n117440512\n74252288\n64618496\n147062784\n156762112\n34144256\n70516736\n160563200\n254803968\n70713344\n91881472\n18219008\n205520896\n231538688\n44040192\n2490368\n16777216\n233111552\n256507904\n24641536\n92274688\n224198656\n246939648\n133300224\n63963136\n35192832\n154271744\n157286400\n47710208\n80150528\n262406144\n184811520\n33554432\n25231360\n118882304\n228458496\n233308160\n126812160\n130547712\n48496640\n85983232\n109117440\n7995392\n71565312\n94371840\n2293760\n15728640\n86769664\n69206016\n7143424\n117309440\n75759616\n40370176\n102170624\n120324096\n212598784\n204472320\n138084352\n20840448\n49545216\n181927936\n166789120\n159645696\n239730688\n218103808\n87621632\n112852992\n260308992\n174587904\n71892992\n23330816\n20578304\n141557760\n236912640\n33161216\n125698048\n131596288\n237043712\n267649024\n161611776\n109051904\n15007744\n156106752\n143130624\n239075328\n21823488\n133169152\n261881856\n264241152\n143458304\n121765888\n29097984\n146800640\n148570112\n";
int main(){
puts(s.c_str());
return 0;
}