• 【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
    ",a.m[0].count());
        }
     
     
    }
    

      

  • 相关阅读:
    常见网络攻击手段原理分析
    admins.py总结比较,转
    django的表与表之间的关系详细讲解
    django中的@login_required
    安装指定版本的第三方库
    在django中使用logging
    django的manytomany总结
    manyToManyField理解和用法
    django的多对一,一对一,多对多关系
    python 的os的总结
  • 原文地址:https://www.cnblogs.com/zhangbuang/p/11202620.html
Copyright © 2020-2023  润新知