[BZOJ2462]矩阵模板(暴力||矩阵hash)

来源:互联网 发布:淘宝的卖家中心不见了 编辑:程序博客网 时间:2024/05/22 12:57

题目描述

传送门

题解

朴素的暴力就能A掉,数据弱。
学习了一下矩阵hash。
感觉非常玄学;刚开始把每一行转化成2进制数,然后把所有的行合并起来转化成2b进制数,就得到了一个矩阵的hash值。
算出来所有小矩阵的hash值,然后把大矩阵里的每一个小矩阵的hash值也算出来,查找就行了。
很玄学的是%的数,貌似让它直接炸掉就可以了= =两次模的是一样的数?
TA说概率很科学。

代码

暴力

#include<iostream>#include<cstring>#include<cstdio>using namespace std;int n,m,a,b,q;int A[1005][1005],B[1005][1005];bool flag;char s[1005];int main(){    scanf("%d%d%d%d\n",&n,&m,&a,&b);    for (int i=1;i<=n;++i){        gets(s);        for (int j=1;j<=m;++j)          A[i][j]=s[j-1]-'0';    }    scanf("%d\n",&q);    while (q--){        for (int i=1;i<=a;++i){            gets(s);            for (int j=1;j<=b;++j)              B[i][j]=s[j-1]-'0';        }        for (int i=1;i<=n-a+1;++i)          for (int j=1;j<=m-b+1;++j){            flag=true;            for (int k=1;k<=a;++k)              for (int l=1;l<=b;++l)                if (A[i+k-1][j+l-1]!=B[k][l]){                    flag=false;                    k=a+1;                    l=b+1;                }            if (flag) {                i=n+1;                j=m+1;            }          }        if (flag) printf("1\n");        else printf("0\n");    }}

hash

#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>#include<vector>using namespace std;#define ll unsigned long longconst int max_n=1e3+5;int n,m,a,b,q;char s[max_n];int A[max_n][max_n],B[max_n][max_n];ll S;ll mt[max_n][max_n],squ[max_n];ll mi2[max_n],miS[max_n];ll hash[max_n*max_n],temp;int main(){    scanf("%d%d%d%d\n",&n,&m,&a,&b);    S=1<<b;    int N=max(a,b);    mi2[0]=1;    for (int i=1;i<=N;++i)      mi2[i]=mi2[i-1]*2;    miS[0]=1;    for (int i=1;i<=N;++i)      miS[i]=miS[i-1]*S;    for (int i=1;i<=n;++i){        gets(s);        for (int j=1;j<=m;++j)          A[i][j]=s[j-1]-'0';    }    for (int i=1;i<=n;++i){        ll ans=0;        for (int j=1;j<=b;++j)          ans=ans+A[i][j]*mi2[b-j];        mt[i][1]=ans;        for (int j=2;j<=m-b+1;++j){            ll head=A[i][j-1];            ll tail=A[i][j+b-1];            ans=ans*2-head*mi2[b]+tail;            mt[i][j]=ans;        }    }    for (int i=1;i<=m-b+1;++i){        ll ans=0;        for (int j=1;j<=a;++j)          ans+=mt[j][i]*miS[a-j];        hash[++temp]=ans;        for (int j=2;j<=n-a+1;++j){            ll head=mt[j-1][i];            ll tail=mt[j+a-1][i];            ans=ans*S-head*miS[a]+tail;            hash[++temp]=ans;        }    }    temp=unique(hash+1,hash+temp+1)-hash-1;    sort(hash+1,hash+temp+1);    scanf("%d\n",&q);    while (q--){        if (n<a||m<b){            puts("0");            continue;        }        for (int i=1;i<=a;++i){            gets(s);            for (int j=1;j<=b;++j)              B[i][j]=s[j-1]-'0';        }        for (int i=1;i<=a;++i){            ll ans=0;            for (int j=1;j<=b;++j)              ans=ans+B[i][j]*mi2[b-j];            squ[i]=ans;        }        ll ans=0;        for (int i=1;i<=a;++i)          ans+=squ[i]*miS[a-i];        if (hash[ lower_bound(hash+1,hash+temp+1,ans)-hash ]==ans) puts("1");        else puts("0");    }}

总结

%的数还是要搞懂一下。

0 0
原创粉丝点击