//题意:简化题意后,给你t组数据,每组数据包括6个小于10000000的整数,这6个数围成一个圈,这6个数相同的前提是,例如:1 2 3 4 5 6和3 2 1 6 5 4是一样的,其实意思只要围成的圈是一样的就行,圈相同说明每一个数字相邻的两个数字肯定相同(想象一下类似循环队列的那个圈)。当然有很多种情况,只要有两个数列围成的圈相同就输出相同,都不相同输出都不相同。
//思路:此题转化到判断序列的排序问题,那么想象一下,要判断两个圈相同只需要判断6个数字,按照某种顺序都相同即可,那么枚举出来,假设有两个圈分别为c1, c2,那么首先按照顺时针枚举,这样枚举:c1[0]~c1[5]与c2[0]~c2[5]若都相同则相同,若不相同,下次枚举c1[0]~c1[5]与c2[1],c2[2],c2[3],c2[4],c2[5],c2[0],一次类推,共枚举36个按照顺时针;其次按照逆时针枚举36个,这样枚举:c1[0]~c1[5]与c2[0],c2[5],c2[4],c2[3],c2[2],c2[1];c2[1],c2[0],c2[5],c2[4],c2[3],c2[2]以此类推。
//3584K 2891MS
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int data[100010][6];
int h[150000];
int hash_k(int i)
{
int sum = 0;
for(int j = 0; j < 6; j++){
sum += data[i][j]%149999;
sum %= 149999;
}
return sum;
}
bool cmp(int l, int n)
{
for(int i = 0; i < 6; i++){
bool eq = true;
for(int j = 0; j < 6; j++){
if(data[l][j] != data[n][(i+j)%6]){
eq = false;
break;
}
}
if(eq)
return true;
}
for(int i = 12; i >=7; i--){
bool eq = true;
for(int j = 0; j < 6; j++){
if(data[l][j] != data[n][(i-j)%6]){
eq = false;
break;
}
}
if(eq)
return true;
}
return false;
}
int main()
{
int key, keyy, t;
int n ;
scanf("%d", &n);
bool ok = false, isT = false;
for(int i = 1; i <= n; i++){
for(int j = 0; j < 6; j++){//这里输入按照字符输入,改为getchar此题只需300ms即可
scanf("%d", &data[i][j]);
}
key = hash_k(i);
keyy = key;
t = 1;
while(h[keyy] != 0){
ok = cmp(h[keyy], i);
if(ok){
printf("Twin snowflakes found.\n");
isT = true;
break;
}
keyy = (key + t*t)%149999;//这是见表的一个公式,不唯一
t++;
}
h[keyy] = i;
}
if(!isT)
printf("No two snowflakes are alike.\n");
return 0;
}