BZOJ1567 [JSOI2008]Blue Mary的战役地图 二分答案 哈希

欢迎访问~原文出处——博客园-zhouzhendong

去博客园看该题解


题目传送门 - BZOJ1567


题意概括

  给出两个n*n的数字矩阵,问最大公共正方形边长。


题解

  先二分答案一个m,对于每一个m,哈希大矩阵中每一个位置上的边长为m的正方形,然后排序,lower_bound一下判定即可。

  鬼畜的是,我的代码在BZOJ上面过去了,but和hzwer大佬(Orz)的代码对拍没有过去,不知道怎么回事……


代码

#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
using namespace std;
typedef long long LL;
const int N=50+5;
LL n,a[N][N],b[N][N],a1[N][N],a2[N][N],b1[N][N],b2[N][N],A[N*N],B[N*N];
bool check(LL m){
	LL mod=2333333333LL,p=1000000007LL,pm=1;
	for (int i=1;i<=m;i++)
		pm=pm*p%mod;
	memset(a1,0,sizeof a1);
	memset(a2,0,sizeof a2);
	memset(b1,0,sizeof b1);
	memset(b2,0,sizeof b2);
	memset(A,0,sizeof A);
	memset(B,0,sizeof B);
	for (int i=1;i<=n;i++)
		for (int j=1;j+m-1<=n;j++)
			for (int k=1;k<=m;k++)
				a1[i][j]=(a1[i][j]*p+a[i][j+k-1])%mod;
	for (int i=1;i+m-1<=n;i++)
		for (int j=1;j+m-1<=n;j++)
			for (int k=1;k<=m;k++)
				a2[i][j]=(a2[i][j]*pm+a1[i+k-1][j])%mod;
	for (int i=1;i<=n;i++)
		for (int j=1;j+m-1<=n;j++)
			for (int k=1;k<=m;k++)
				b1[i][j]=(b1[i][j]*p+b[i][j+k-1])%mod;
	for (int i=1;i+m-1<=n;i++)
		for (int j=1;j+m-1<=n;j++)
			for (int k=1;k<=m;k++)
				b2[i][j]=(b2[i][j]*pm+b1[i+k-1][j])%mod;
	int tot=0;
	for (int i=1;i+m-1<=n;i++)
		for (int j=1;j+m-1<=n;j++)
			A[++tot]=a2[i][j],B[tot]=b2[i][j];
	sort(A+1,A+tot+1);
	sort(B+1,B+tot+1);
	for (int i=1;i<=tot;i++)
		if (A[lower_bound(A+1,A+tot+1,B[i])-A]==B[i])
			return 1;
	return 0;
}
int main(){
	scanf("%lld",&n);
	for (int i=1;i<=n;i++)
		for (int j=1;j<=n;j++)
			scanf("%lld",&a[i][j]),a[i][j]+=1LL<<31;
	for (int i=1;i<=n;i++)
		for (int j=1;j<=n;j++)
			scanf("%lld",&b[i][j]),b[i][j]+=1LL<<31;
	LL le=1,ri=n,mid,ans=0;
	while (le<=ri){
		mid=(le+ri)>>1;
		if (check(mid))
			le=mid+1,ans=mid;
		else
			ri=mid-1;
	}
	printf("%lld",ans);
	return 0;
}

  

posted @ 2017-08-28 22:10  zzd233  阅读(266)  评论(0编辑  收藏  举报