牛客國慶集訓派對Day2 A
阿新 • • 發佈:2018-12-13
題目描述
深度學習演算法很大程度上基於矩陣運算。例如神經網路中的全連線,本質上是一個矩陣乘法;而卷積運算也通常是用矩陣乘法來完成的。有一些科研工作者為了讓神經網路的計算更快捷,提出了二值化網路的方法,就是將網路權重壓縮成只用兩種值表示的形式,這樣就可以用一些 trick 加速計算了。例如兩個二進位制向量點乘,可以用計算機中的與運算代替,然後統計結果中 1 的個數即可。 然而有時候為了降低壓縮帶來的誤差,只允許其中一個矩陣被壓縮成二進位制。這樣的情況下矩陣乘法運算還能否做進一步優化呢?給定兩個整數矩陣A, B,計算矩陣乘法 C = A x B。為了減少輸出,你只需要計算 C 中所有元素的的異或和即可。
輸入描述:
第一行有三個整數 N, P, M, 表示矩陣 A, B 的大小分別是 N x P, P x M 。 接下來 N 行是矩陣 A 的值,每一行有 P 個數字。第 i+1 行第 j 列的數字為 Ai,j, Ai,j 用大寫的16進製表示(即只包含 0~9, A~F),每個數字後面都有一個空格。 接下來 M 行是矩陣 B 的值,每一行是一個長為 P 的 01字串。第 i + N + 1 行第 j 個字元表示 Bj,i 的值。
輸出描述:
一個整數,矩陣 C 中所有元素的異或和。
示例1
輸入
4 2 3 3 4 8 A F 5 6 7 01 11 10
輸出
2
說明
矩陣 C 的值為: 4 7 3 10 18 8 5 20 15 7 13 6
備註:
2 ≤ N, M ≤ 4096, 1 ≤ P ≤ 64, 0 ≤ Ai,j< 65536.
思路:
p最多64,那麼可將矩陣A的每一行縱向切割,最多切割8塊,矩陣B的每一列,橫向切割,最多切割8塊,矩陣B是01串,那麼每一列的每一塊的值就有256種,可將矩陣A與矩陣B分塊後這256種情況相乘的結果先預處理求出來,再進行求最後答案。大概就是通過減小p值(矩陣分塊)來降低複雜度的吧~
程式碼如下:
#include<iostream> #include<cstdio> #include<algorithm> #include<vector> #include<cmath> #include<set> #include<string> #include<cstring> #define ll long long using namespace std; const int N=4100; int A[N][N],B[N][N]; int Ap[N][10][260],Bp[N][10]; int n,p,m; int main(){ char ch; scanf("%d%d%d",&n,&p,&m); for(int i=0;i<n;i++){ for(int j=0;j<p;j++){ scanf("%x",&A[i][j]); } } for(int i=0;i<p;i++){ for(int j=0;j<m;j++){ scanf("%1d",&B[j][i]); } } p=(p-1)/8+1;//矩陣B分成p塊 //預處理A矩陣,將其分塊,並將每一塊對應的256種情況預處理出來 //Ap[i][j][k]:=將第i行第j快與對應的k所代表的的8位二進位制塊相乘所得的結果 for(int i=0;i<n;i++){ for(int j=0;j<p;j++){ int base=j*8; for(int k=0;k<256;k++){//對應矩陣B的分出的小塊的值 for(int b=0;b<8;b++){ //1<<b表示B矩陣這一位上的數是1,如果對應的k值這一位上也是1 //說明Ap[i][j][k]的值需要加上A矩陣對應的值 if(k&(1<<b))Ap[i][j][k]+=A[i][base+b]; } } } } //處理矩陣B,將其分塊,並將其每塊對應的二進位制串所對應的整數求出來 for(int i=0;i<m;i++){ for(int j=0;j<p;j++){ int base=j*8; for(int k=0;k<8;k++){ Bp[i][j]+=(B[i][base+k]<<k); } } } //利用預處理出來的結果,將c[i][j]所對應的塊的相乘的值加起來 int ans=0,tmp; for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ tmp=0; for(int k=0;k<p;k++){ tmp+=Ap[i][k][Bp[j][k]]; } ans^=tmp; } } printf("%d\n",ans); }