注意到这个在哈希时要考虑循环同构。。。所以哈希函数是$sum a_i+prod a_i$
如果发现有哈希值相等的了就$ck$一下。
最后$ck$时可以用最小表示法的知识提高效率,,,先咕着。
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<cmath> #include<cctype> #include<cstdlib> #include<vector> #include<queue> #include<map> #include<set> #define ll long long #define R register int using namespace std; namespace Fread { static char B[1<<15],*S=B,*D=B; #define getchar() (S==D&&(D=(S=B)+fread(B,1,1<<15,stdin),S==D)?EOF:*S++) inline int g() { R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-1:fix; do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix; } }using Fread::g; const int N=100010,p=99991; int n; struct node { int fir[N],nxt[N],s[N][6],cnt; inline void clear() { memset(fir,0,sizeof(fir)),memset(nxt,0,sizeof(nxt)); memset(s,0,sizeof(s)),cnt=0; } inline int hsh(int* d) { R sum=0,mul=1; for(R i=0;i<6;++i) sum=(sum+d[i])%p,mul=(ll)mul*d[i]%p; return (sum+mul)%p; } inline bool ck(int* a,int* b) { for(R i=0;i<6;++i) for(R j=0;j<6;++j) { register bool flg=1; for(R k=0;k<6;++k) if(a[(i+k)%6]!=b[(j+k)%6]) flg=0; if(flg) return 1; flg=1; for(R k=0;k<6;++k) if(a[(i+k)%6]!=b[(j-k+6)%6]) flg=0; if(flg) return 1; } return 0; } inline bool ins(int* d) { R st=hsh(d); for(R i=fir[st];i;i=nxt[i]) if(ck(s[i],d)) return 1; ++cnt; memcpy(s[cnt],d,sizeof(int)*6); nxt[cnt]=fir[st],fir[st]=cnt; return 0; } }HSH; signed main() { #ifdef JACK freopen("NOIPAK++.in","r",stdin); #endif n=g(); for(R i=1;i<=n;++i) { R x[7]; for(R j=0;j<6;++j) x[j]=g(); if(HSH.ins(x)) { printf("Twin snowflakes found. "); return 0;} } printf("No two snowflakes are alike. "); }
2019.06.10