枚举前后两个面是啥,然后卡常即可。观察样例可以发现这样会计算每种情况24遍。
(我也不知道为啥啊XD)
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<unordered_map>
#define N 410
#define lint long long
#define ull unsigned long long
#define gc getchar()
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
inline int inn()
{
int x,ch;while((ch=gc)<'0'||ch>'9');
x=ch^'0';while((ch=gc)>='0'&&ch<='9')
x=(x<<1)+(x<<3)+(ch^'0');return x;
}
int Gc;unordered_map<lint,int> cnt;lint val[1000];
int c[N][5];lint cv[N][4];
inline lint hv(int a,int b,int c,int d)
{
return a*1000000000ll+b*1000000ll+c*1000ll+d;
}
inline lint hv(int *a)
{
return hv(a[0],a[1],a[2],a[3]);
}
inline int Rot(int *a,int c)
{
rep(i,1,c)
{
int tmp=a[0];
rep(j,1,3) a[j-1]=a[j];
a[3]=tmp;
}
return 0;
}
inline int Add(int x)
{
rep(i,0,3) cnt[cv[x][i]]++;
return 0;
}
inline int Del(int x)
{
rep(i,0,3) cnt[cv[x][i]]--;
return 0;
}
inline int Get(int a,int b,int c,int d)
{
int t=cnt[hv(a,b,c,d)];
if(!t) return 0;
cnt[val[++Gc]=hv(a,b,c,d)]--;
cnt[val[++Gc]=hv(b,c,d,a)]--;
cnt[val[++Gc]=hv(c,d,a,b)]--;
cnt[val[++Gc]=hv(d,a,b,c)]--;
return t;
}
inline int Back()
{
rep(i,1,Gc) cnt[val[i]]++;
Gc=0;return 0;
}
int main()
{
int n=inn();ull ans=0ll;
rep(i,1,n) rep(j,0,3) c[i][j]=inn();
rep(i,1,n)
{
#define a c[i]
cnt[cv[i][0]=hv(a[0],a[1],a[2],a[3])]++;
cnt[cv[i][1]=hv(a[1],a[2],a[3],a[0])]++;
cnt[cv[i][2]=hv(a[2],a[3],a[0],a[1])]++;
cnt[cv[i][3]=hv(a[3],a[0],a[1],a[2])]++;
#undef a
}
rep(i,1,n)
{
Del(i);
rep(p,0,3)
{
// Rot(c[i],p);
rep(j,1,n) if(i!=j)
{
Del(j);
rep(q,0,3)
{
// Rot(c[j],q);
int s,x,z,y;
s=Get(c[j][1],c[j][0],c[i][1],c[i][0]);//S
if(!s) goto loop;
x=Get(c[j][2],c[i][3],c[i][2],c[j][3]);//X
if(!x) goto loop;
z=Get(c[j][1],c[i][0],c[i][3],c[j][2]);//Z
if(!z) goto loop;
y=Get(c[i][1],c[j][0],c[j][3],c[i][2]);//Y
if(!y) goto loop;
ans+=1ll*s*x*z*y;
loop:;
Back();
Rot(c[j],1);
}
Add(j);
}
Rot(c[i],1);
}
Add(i);
}
return !printf("%llu\n",ans/24);
}