//题意:简化题意后,给你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; }