P2601 ZJOI2009 對稱的正方形

2022-05-05 16:21:11 字數 2248 閱讀 2677

#$description$

[題面](

給你一張$n*m$的數字表,問其中有多少個上下對稱且左右對稱的正方形。

#$solution$

這道題真的噁心,首先學習一下二維雜湊,但在學習二維雜湊之前,我們先來看乙個問題

>給你乙個長度為$n$的字串和$q$組詢問,每組詢問是兩個位置和兩個長度代表兩個子串,問這兩個子串是否相等

對於這種題,如果每組$q$都進行$o(n)$的雜湊明顯和暴力沒區別,我們會想到用字首和的思想,對於$i-j$的串,將$hash[j]-hash[i-1]$作為它的雜湊值比較。

但這樣顯然是錯誤的,比如下面這個例子

!(雜湊就是將字串轉換成進製數,假設我們選取十進位制

那麼對於第乙個串$hash[i-1]=33,hash[j]=33568$,第二個串$hash[j]=44568,hash[i-1]=44$,$i-j$的串是相等的,但是通過上面式子計算出來的值顯然不相等。

考慮到字首和的$o(1)$查詢實際就是消除前面的影響,$hash$是乙個進製轉換過程,所以根據乘法分配律前面的$hash[i-1]$對後面的影響實際是$hash[i-1]*base^$,所以$hash[j]-hash[i-1]*base^$就是$i-j$單獨的雜湊值,直接拿來比較就行了,需要提前預處理$base$的次方。

回到二維雜湊的問題,不難想到我們對於乙個\((1,1)-(i,j)\)的矩陣,先把每一行的雜湊值壓成乙個數,這個過程和一維是完全一樣的,就是對原陣列的進製轉換,然後對於每一列將壓縮好的資訊直接再做一次\(hash\),注意這一次不用管原陣列了,注意兩個壓縮過程盡量選用不同的\(base\)比如\(87\)和\(312\)。

如何\(o(1)\)求乙個矩陣的雜湊值?考慮二維字首和,先對行消去影響,再對列消去影響,再對被重複消去的部分容斥

\((x,y)-(i,j)\)的矩陣:\(hash[i][j]-hash[i][y-1]*base1^-hash[x-1][j]*base2^+hash[x-1][y-1]*base1^*base2^\)

以上大功告成

再回到本題,我們判斷乙個正方形是否對稱,只需要預處理按縱軸和按橫軸翻轉的兩個矩陣(相當於映象,將它翻轉),在這三個矩陣中找到同乙個正方形的位置做\(hash\),如果三個\(hash\)值都一樣說明怎麼翻轉這個正方形都完全重合,也就一定是對稱的了。

萬事俱備只欠二分,發現正方形的中點可能落在數字上也可能落在四個數字之間的空格上,對於這兩種情況分別處理。

掃到每乙個這樣的點就二分正方形邊長的一半,然後雜湊\(check\),找到最大的邊長\(x\),易知以該點為中心的正方形邊長\(<=mid\)也一定合法,因此對答案的貢獻是\(ans+=x\)。

1.預處理兩個方向翻轉的二維陣列,以及對這三個陣列做二維\(hash\)

2.對於每乙個點二分擴充套件,分中點在數字上和中點在空格上考慮,找到最大邊長\(ans+=x\)

3.最後\(ans+=m*n\),因為每個小正方形也是答案

總複雜度\(o(nmlogn)\)

#include#include#include#include#define re register

#define int unsigned long long

#define base1 87

#define base2 312

const int maxn=1010;

using namespace std;

inline int read()

while(ch>='0'&&ch<='9')

return x*f;

}int n,m,ans;

int a[maxn][maxn],b[maxn][maxn],fac1[maxn],fac2[maxn];

int bb[maxn][maxn],le[maxn][maxn],bbb[maxn][maxn],up[maxn][maxn];

void copys()

void hasha()

inline int check(int x,int y,int len)

else r=mid-1;

} ans+=sums;

} for(re int i=1;i>1;

if(check(i+mid,j+mid,mid+mid+1))

else r=mid-1;

} ans+=sums;

} ans+=n*m;//別忘了加上

return;

}signed main()

ZJOI2009 對稱的正方形(矩陣雜湊 二分)

時間限制 1000ms 1000ms 1000ms 記憶體限制 128mb 128 mb 128m b 問題描述 o re zorez orez 很喜歡蒐集一些神秘的資料,並經常把它們排成乙個矩陣進行研究。最近,ore zorez orez 又得到了一些資料,並已經把它們排成了乙個n nn行m mm...

洛谷 P2601 hash 對稱的正方形

和這個相似 只是變成了二維 對稱有兩種,上下和左右 處理3次hash 原來的矩形,上下翻轉後的,左右翻轉後的 列舉中心點 二分出最大的對稱正方形的邊長 以這個正方形的中心且比ta小的正方形也是對稱的 即可算入貢獻 include include using namespace std const i...

P2055 ZJOI2009 假期的宿舍

題目描述 學校放假了 有些同學回家了,而有些同學則有以前的好朋友來探訪,那麼住宿就是乙個問題。比如 a 和 b 都是學校的學生,a 要回家,而 c 來看b,c 與 a 不認識。我們假設每個人只能睡和自己直接認識的人的床。那麼乙個解決方案就是 b 睡 a 的床而 c 睡 b 的床。而實際情況可能非常複...