头一次见这么卡常的题(仅限bzoj),还没卡过,不过省选的数据和时限应该没啥问题
这个题出的不太好,毕竟看脸,但出题人卡一些hash又放过一些hash真是不懂为什么
码(tle):
#include<cstdio>
#include<cstring>
int n,m,a,b,i,tu[1005][1005],j,k,l,lhash1,hash1[15];
long long P=998244353,qsum[1005][1005],qsum2[1005],ni[200005],er[20005];
char ch;
int ans[15],q;
long long x,y;
void exgcd(long long a,long long m)
{
if(m==0)
{
x=1;
y=0;
return;
}
exgcd(m,a%m);
long long temp=y;
y=x-a/m*y;
x=temp;
}
int main()
{
scanf("%d%d%d%d",&n,&m,&a,&b);
er[0]=1;
for(i=1;i<=a*b;i++)
er[i]=(er[i-1]*2)%P;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
ch=getchar(); while(ch!='0'&&ch!='1')ch=getchar();
tu[i][j]=ch-'0';
}
scanf("%d",&q);
for(k=1;k<=q;k++)
{
for(i=1;i<=a;i++)
for(j=1;j<=b;j++)
{
ch=getchar();
while(ch!='0'&&ch!='1')ch=getchar();
hash1[k]=(hash1[k]*2%P+(ch-'0'))%P;
}
}
for(i=1;i<=m;i++)
for(j=1;j<=n;j++)
{
qsum[i][j]=(qsum[i][j-1]*er[b]%P+tu[j][i]*er[b-1]%P)%P;
}
for(i=1;i<=n;i++)
for(j=1;j<=b;j++)
{
qsum2[i]=(qsum2[i]*2%P+tu[i][j])%P;
}
ni[0]=1;
for(i=1;i<=a*b;i++)
{
exgcd(er[i],P);
ni[i]=(x+P)%P;
}
for(i=a;i<=n;i++)
{
lhash1=0;
for(j=i-a+1;j<=i;j++)
{
lhash1=(lhash1*er[b]%P+qsum2[j])%P;
}
for(k=1;k<=q;k++)
{
if(lhash1==hash1[k]||lhash1+P==hash1[k])ans[k]=1;
}
for(j=b+1;j<=m;j++)//右下角坐标
{
lhash1=((lhash1-(qsum[j-b][i]-qsum[j-b][i-a]*er[a*b]%P)%P)+P)%P; //清掉左列
lhash1=lhash1*2%P;
lhash1=(lhash1+((qsum[j][i]-qsum[j][i-a]*er[a*b]%P)%P*ni[b-1])+P)%P;
for(k=1;k<=q;k++)
{
if(lhash1==hash1[k]||lhash1+P==hash1[k])ans[k]=1;
}
}
}
for(i=1;i<=q;i++)
{
printf("%d\n",ans[i]);
}
}