给你一个n*n的矩阵A,和一个m*m的矩阵B(m%2==1)
B是卷积核,让你用B对A做t次卷积运算,并且对于A中的每一个元素计算出来的值要模2,所以A最后会是一个01矩阵。
问你经过t此后,A中有多少个元素=1
1<=t<=1e9,1<=n<=8,1<=m<=n
SOLUTION:
二维矩阵展成1维
那么做法就是把A矩阵变成一个1*(n*n)的一维向量,然后构造一个(n*n)*(n*n)的辅助矩阵
我们观察到对于A中的每一个元素,每一次卷积运算,所要求乘积的值的位置是固定的,那么我们就提前预处理出
因为值只有0和1,所以可以用bitset加速
CODE:
#include <cstdio> #include <algorithm> #include <cstring> #include <bitset> using namespace std; typedef long long ll; const int MOD = 2; const int MAXN = 40000; typedef struct { bitset<80> m[80]; int sizx,sizy; }Matrix; int n,m; Matrix cb; inline Matrix Mul(Matrix a, Matrix b) { Matrix c; c.sizx=a.sizx; c.sizy=b.sizy; cb.sizy=b.sizx; cb.sizx=b.sizy; for(int i=0;i<b.sizy;i++) { cb.m[i].reset(); for(int j=0;j<b.sizx;j++) { cb.m[i][j]=b.m[j][i]; } } for (int i = 0; i < a.sizx; i++) { c.m[i].reset(); for (int j = 0; j < b.sizy; j++) { bitset<80> tmp=(a.m[i]&cb.m[j]); c.m[i][j]=tmp.count()&1; } } return c; } inline Matrix fastm(Matrix a, ll num) { Matrix res; for(int i=0;i<a.sizx;i++) res.m[i].reset(); res.sizx=a.sizx; res.sizy=a.sizy; for(int i=0;i<a.sizx;i++) res.m[i][i]=1; while (num) { if (num & 1) res = Mul(res, a); num >>= 1; a = Mul(a, a); } return res; } Matrix a,b,c; int main() { int cas; scanf("%d",&cas); while(cas--) { int t; scanf("%d%d%d",&n,&m,&t); a.sizx=1;a.sizy=n*n; a.m[0].reset(); for(int i=0;i<n*n;i++) { int tmp; scanf("%d",&tmp); a.m[0][i]=tmp&1; } for(int i=0;i<m;i++) { for(int j=0;j<m;j++) { int tmp; scanf("%d",&tmp); b.m[i][j]=tmp&1; } } c.sizx=c.sizy=n*n; int num=0; int in=0; m=m>>1; for(int i=0;i<n*n;i++) c.m[i].reset(); for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { for(int p=i-m;p<=i+m;p++) { for(int q=j-m;q<=j+m;q++) { in=p*n+q; if(p>=0&&p<n&&q>=0&&q<n) { c.m[in][num]=(b.m[p-i+m][q-j+m]); } } } num++; } } c=fastm(c,t); a=Mul(a,c); printf("%d\n",a.m[0].count()); } }
原文地址:https://www.cnblogs.com/zhangbuang/p/11202620.html
时间: 2024-11-05 23:18:54