【Ybtoj 第7章例题5】子正方形【哈希】

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


解题思路

这道题矩阵大小才 50 ,我们可以直接用 hash 暴搜。

先枚举两个矩阵所选的矩阵的右下角,然后再二分枚举矩阵大小,取最大值即可。


代码

#include<iostream>
#include<cstdio>
#include<iomanip>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ull unsigned long long 

const ull p=131,q=313;
using namespace std;

int n,a[60][60],b[60][60],l,r,mid,ans;
ull hs1[60][60],hs2[60][60];

struct c{
	ull x,y;
}base[60];

bool check(int mid,int x,int y,int xx,int yy){
	return ((hs1[x][y]-hs1[x-mid][y]*base[mid].x-hs1[x][y-mid]*base[mid].y+hs1[x-mid][y-mid]*base[mid].x*base[mid].y)==
	(hs2[xx][yy]-hs2[xx-mid][yy]*base[mid].x-hs2[xx][yy-mid]*base[mid].y+hs2[xx-mid][yy-mid]*base[mid].x*base[mid].y));
}

int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			scanf("%d",&a[i][j]);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			scanf("%d",&b[i][j]);
			
	base[0].x=base[0].y=1ull;
	for(int i=1;i<=n;i++) base[i].x=base[i-1].x*p;
	for(int i=1;i<=n;i++) base[i].y=base[i-1].y*q;
	
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			hs1[i][j]=hs1[i-1][j]*p+a[i][j];
			hs2[i][j]=hs2[i-1][j]*p+b[i][j];
		}	
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			hs1[i][j]+=hs1[i][j-1]*q;
			hs2[i][j]+=hs2[i][j-1]*q;
		}	
	}
	
	
	for(int sx=1;sx<=n;sx++)
		for(int sy=1;sy<=n;sy++)
			for(int tx=1;tx<=n;tx++)
				for(int ty=1;ty<=n;ty++)
				{
					l=0,r=min(min(sx,sy),min(tx,ty));
					while(l<=r)
					{
						mid=(l+r)>>1;
						if(check(mid,sx,sy,tx,ty))
						{
							ans=max(mid,ans);
							l=mid+1;
						}
						else r=mid-1;
					}
					
				}
	printf("%d",ans);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值