这是一道可以练习哈希表的模板题。关于哈希表的操作均有涉及。
哈希函数的选取是这道题的关键。这道题的关键字是一个长度为6的序列,并且序列与开始顺序、时钟顺序均无关。
因此,采用哈希函数(H[x]=Sigma_{i=0}^5a[i]+prod_{i=0}^5a[i]),即:用加和乘的相加来进一步保证散列性。
另外,不能采用带“权值“的哈希函数,因为无序性。
另一个小知识点是顺时针和逆时针的操作,顺时针加 k 取模即可,逆时针正常来说减 k 取模即可,不过可能出现负数,因此再加上6。
代码如下
#include <cstdio>
using namespace std;
const int maxn=1e5+10;
const int mod=1e6+3;
int n,d[6];
struct node{
int nxt,snow[6];
}t[maxn];
int tot=1,head[mod];
int calc(int p[6]){
int add=0,mul=1;
for(int i=0;i<6;i++){
add=(add+p[i])%mod;
mul=(long long)mul*p[i]%mod;
}
return (add+mul)%mod;
}
bool equal(int a[6],int b[6]){
for(int i=0;i<6;i++)
for(int j=0;j<6;j++){
bool f1=1,f2=1;
for(int k=0;k<6;k++){
if(a[(i+k)%6]^b[(j+k)%6])f1=0;
if(a[(i+k)%6]^b[(j-k+6)%6])f2=0;
}
if(f1||f2)return 1;
}
return 0;
}
bool insert(int a[6]){
int u=calc(a);
for(int i=head[u];i;i=t[i].nxt)
if(equal(t[i].snow,a))
return 1;
++tot,t[tot].nxt=head[u],head[u]=tot;
for(int i=0;i<6;i++)t[tot].snow[i]=a[i];
return 0;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
for(int j=0;j<6;j++)scanf("%d",&d[j]);
if(insert(d))return puts("Twin snowflakes found."),0;
}
return puts("No two snowflakes are alike."),0;
}