题面
https://www.luogu.org/problem/P2601
题解
二维哈希(和二维前缀和类似)
右向量:$107$
下向量:$233$
才不会取名叫$wls$和$wym$
upd:突然想到,取$wls$和$wym$也挺好的,因为他们作为两个基向量,被我期待在任何一点永不相交。
讽刺的是,现实生活中,他们一个在一中,一个在七中,竟然还能谈成。。。这说明我的哈希是失败的。
想起了合肥市第四十五中学2015级4班著名作家$lyh$曾经写的一篇循环周记,讽刺这件事:
一个猎人打猎,打到了一匹小马(我这么喊她),试图让小马当自己的坐骑,然后小马桀骜不驯,为了追求自由,自杀身亡。
可惜当年,我还能被他们形容成猎人这个虽然邪恶但是充满力量的人物,还是很看得起我的,现在,估计当年的马尥一下蹶子就把我踹死了吧。现在的八中人,也没有人这么说吧($wym$在七中前$50$名,我在八中$1000$名)
不想这些无聊的东西了,我还是好好想我女神吧。好在我女神还是一中前$50$的,女神最可爱啦。
#include<cstdio> #include<iostream> #include<cstring> #define N 1050 #define ri register int #define uLL unsigned long long using namespace std; const uLL p1=107,p2=233; uLL pp1[N],pp2[N]; int n,m; int a[N][N]; struct hash{ uLL sum1[N][N],sum2[N][N],sum3[N][N],sum4[N][N]; void init() { for (ri i=1;i<=n;i++) for (ri j=1;j<=m;j++) sum1[i][j]=sum1[i-1][j]*p1+sum1[i][j-1]*p2-sum1[i-1][j-1]*p1*p2+(uLL)a[i][j]; for (ri i=n;i>=1;i--) for (ri j=1;j<=m;j++) sum2[i][j]=sum2[i+1][j]*p1+sum2[i][j-1]*p2-sum2[i+1][j-1]*p1*p2+(uLL)a[i][j]; for (ri i=1;i<=n;i++) for (ri j=m;j>=1;j--) sum3[i][j]=sum3[i-1][j]*p1+sum3[i][j+1]*p2-sum3[i-1][j+1]*p1*p2+(uLL)a[i][j]; for (ri i=n;i>=1;i--) for (ri j=m;j>=1;j--) sum4[i][j]=sum4[i+1][j]*p1+sum4[i][j+1]*p2-sum4[i+1][j+1]*p1*p2+(uLL)a[i][j]; } uLL s1(int a,int b,int x,int y){ return sum1[x][y]-sum1[a-1][y]*pp1[x-a+1]-sum1[x][b-1]*pp2[y-b+1]+sum1[a-1][b-1]*pp1[x-a+1]*pp2[y-b+1]; } uLL s2(int a,int b,int x,int y){ return sum2[x][y]-sum2[a+1][y]*pp1[a-x+1]-sum2[x][b-1]*pp2[y-b+1]+sum2[a+1][b-1]*pp1[a-x+1]*pp2[y-b+1]; } uLL s3(int a,int b,int x,int y){ return sum3[x][y]-sum3[a-1][y]*pp1[x-a+1]-sum3[x][b+1]*pp2[b-y+1]+sum3[a-1][b+1]*pp1[x-a+1]*pp2[b-y+1]; } uLL s4(int a,int b,int x,int y){ return sum4[x][y]-sum4[a+1][y]*pp1[a-x+1]-sum4[x][b+1]*pp2[b-y+1]+sum4[a+1][b+1]*pp1[a-x+1]*pp2[b-y+1]; } int check1(int x,int y) { int lb=1,rb=min(min(x-1,y-1),min(n-x,m-y)); int ret=0; while (lb<=rb) { int mid=(lb+rb)/2; uLL t1=s1(x-mid,y-mid,x,y); uLL t2=s2(x+mid,y-mid,x,y); uLL t3=s3(x-mid,y+mid,x,y); uLL t4=s4(x+mid,y+mid,x,y); if (t1==t2 && t2==t3 && t3==t4) ret=mid,lb=mid+1; else rb=mid-1; } return ret+1; } int check2(int x,int y) { int lb=1,rb=min(min(x-1,y-1),min(n-1-x,m-1-y)); int ret=0; while (lb<=rb) { int mid=(lb+rb)/2; uLL t1=s1(x-mid,y-mid,x,y); uLL t2=s2(x+1+mid,y-mid,x+1,y); uLL t3=s3(x-mid,y+1+mid,x,y+1); uLL t4=s4(x+mid+1,y+mid+1,x+1,y+1); if (t1==t2 && t2==t3 && t3==t4) ret=mid,lb=mid+1; else rb=mid-1; } return ret+1; } } H; int main(){ pp1[0]=1; pp2[0]=1; for (ri i=1;i<N;i++) pp1[i]=pp1[i-1]*p1,pp2[i]=pp2[i-1]*p2; scanf("%d %d",&n,&m); for (ri i=1;i<=n;i++) for (ri j=1;j<=m;j++) scanf("%d",&a[i][j]); H.init(); int ans=0; for (ri i=1;i<=n;i++) for (ri j=1;j<=m;j++) { ans+=H.check1(i,j); if (a[i][j]==a[i+1][j] && a[i+1][j]==a[i][j+1] && a[i][j+1]==a[i+1][j+1]) ans+=H.check2(i,j); } cout<<ans<<endl; }