あなたは、n * nの行列Aを与え、M * Mの行列B(M%2 == 1)
Aは、最終的に01行列になるようあなたは、T回畳み込み演算へ、及びモジュロ2の演算値の各要素にBを使用しないので、Bは、畳み込みカーネルです。
あなたはトンを通じて要素の数= 1で、Aを確認して下さい
1 <= T <= 1e9,1 <= N <= 8,1 <= M <= N
溶液:
一次元に展開2次元マトリクス
マトリックスアプローチは次いで補助マトリックス(N * N)* 1 *(N×n個)一次元ベクトルに入れ、及び(N×n個)を構成されています
我々は、我々は、前処理を進め、元素Aのそれぞれに対して、所望の位置の値の各畳み込み積が一定であることが観察され
のみ値0と1なぜなら、それはビット集合によって加速することができます
コード:
#include <cstdioを>
する#include <アルゴリズム>
の#include <CStringの>
する#include <ビットセット>
使用して名前空間std。
typedefの長い長いLL。
const int型MOD = 2;
const int型MAXN = 40000;
構造体のtypedef {
ビット集合<80> M [80]。
int型sizx、sizy。
}マトリックス;
N INT、M。
行列CB。
インラインマトリックスムル(マトリックス、行列B)
{
行列C。
c.sizx = a.sizx。
c.sizy = b.sizy。
cb.sizy = b.sizx。
cb.sizx = b.sizy。
以下のために(; iは<b.sizy I ++は、I = 0 INT)
{
cb.mを[I] .RESET()。
(J ++ INT J = 0; J <b.sizx)のために
{
cb.m [I] [J] = BM [J] [I];
}
}
のために(iは++; iは<a.sizx I = 0 INT)
{
[I] .RESET()センチ。
用(int型J = 0; J <b.sizy; J ++)
{
ビット集合<80> TMP =(AM [I]&cb.m [J])。
CM [I] [J] = tmp.count() - 1;
}
}
戻りC。
}
インラインマトリックスfastm(LLのNUMを行列)
{
マトリックスRES。
res.m [I] .RESET()のために(; I <a.sizx I ++は、I = 0をINT)。
res.sizx = a.sizx。
res.sizy = a.sizy。
(; iがa.sizx <I ++はiが0 = INT)のため
res.m [i]は[I] = 1。
一方、(NUM)
{
IF(NUM&1)
RES =ムル(RES、A)。
NUM >> = 1;
=ムル(A)。
}
RESを返します。
}
、B、Cのマトリックス。
INTのmain()
{
int型CAS。
scanf関数( "%dの"、およびCAS)。
(cas--)一方
{
int型のT。
scanf関数( "%D%D%D"、&N、&M&T)。
a.sizx = 1; a.sizy = N * N。
[0] .RESET()しています。
以下のために(; iがn <N *; i = 0はint型私は++)
{
int型TMP。
scanf関数( "%のD"、&TMP)。
午前[0] [I] = tmpに&1;
}
(i = 0 int型私は++;私がm <)のために
{
(INT J = 0; J <M。
scanf関数( "%のD"、&TMP)。
[I] [J] = tmpのBM&1。
}
}
c.sizx = c.sizy = N * N。
int型NUM = 0;
= 0のint;
M = M >> 1。
CM [I] .RESET()は(iは++; N * iがn <I = 0 INT)。
以下のために(INT i = 0; iがN <、iは++)
{
ための(int型J = 0であり、j <nであり、j ++)
{
(INT P = IM; p <= I + M; p ++)のために
{
ため(INT Q = JM; Q <= J + M; Q ++)
{
= P×n個+ Qにおいて、
(pは> = 0 && P <N && qは> = 0 && Q <N)の場合
{
CM [NUM] =(BM [P-iがM +] [Q-J + M])[IN]。
}
}
}
NUM ++。
}
}
C = fastm(C、T)。
=ムル(C);
printf( "%d個の\ n"、[0] .count(AM))。
}
}