2018徐州网络赛Morgana Net (矩阵快速幂)

Posted zhangbuang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2018徐州网络赛Morgana Net (矩阵快速幂)相关的知识,希望对你有一定的参考价值。

给你一个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());
    
 
 

  

以上是关于2018徐州网络赛Morgana Net (矩阵快速幂)的主要内容,如果未能解决你的问题,请参考以下文章

2018 ICPC 徐州网络赛

2018 徐州网络赛 I

2018 徐州网络赛 H

2018 徐州网络赛 B

2018 徐州网络赛 J

2018 徐州网络赛A