分析:
给出N个正方形,每个正方形正面的四个角各有一种颜色,要求组成正方体的方案数(由于每个正方形中间都有一个数字,所以方向不同也算不同方案)。
也就是说,两种方案视为相同,当且仅当一个正方体可以通过各种旋转得到另一个。
分析:
考虑到N非常小(400)
有一个很显然的性质:只要确定了正方体一组正对的面的各个角的颜色,就可以唯一确定整个正方体。
所以。。。不就是爆枚么。。。爆枚一个正方形,再爆枚另一个以及相对方向,作为其对面的,然后一个map存方案即可。
注意一下,因为正方形可以旋转,所以存入map时,要把旋转4次的结果都插入进去。去重的时候也要将旋转之后的各个方案都去掉。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
#define SF scanf
#define PF printf
#define MAXN 100010
using namespace std;
typedef long long ll;
ll ans;
int n;
struct node{
int a1,a2,a3,a4;
node() {}
node(int aa1,int aa2,int aa3,int aa4):a1(aa1),a2(aa2),a3(aa3),a4(aa4) {}
bool operator <(const node &a) const {
if(a1!=a.a1)
return a1<a.a1;
if(a2!=a.a2)
return a2<a.a2;
if(a3!=a.a3)
return a3<a.a3;
return a4<a.a4;
}
bool operator ==(const node &a) const{
if(a1==a.a1&&a2==a.a2&&a3==a.a3&&a4==a.a4)
return 1;
return 0;
}
}t[MAXN];
map<node,ll> used;
void solve(int b1,int b2,int b3,int b4){
used[node(b1,b2,b3,b4)]++;
}
ll check(node x,node y){
ll res=0;
if(x==y)
res++;
int tx=y.a1;
y.a1=y.a2;y.a2=y.a3;y.a3=y.a4;y.a4=tx;
if(x==y)
res++;
tx=y.a1;
y.a1=y.a2;y.a2=y.a3;y.a3=y.a4;y.a4=tx;
if(x==y)
res++;
tx=y.a1;
y.a1=y.a2;y.a2=y.a3;y.a3=y.a4;y.a4=tx;
if(x==y)
res++;
return res;
}
void count(int b1,int b2,int b3,int b4,int b5,int b6,int b7,int b8){
//PF("{%d %d %d %d %d %d %d %d}\n",b1,b2,b3,b4,b5,b6,b7,b8);
node x1=node(b1,b2,b6,b5);
node x2=node(b2,b3,b7,b6);
node x3=node(b3,b4,b8,b7);
node x4=node(b4,b1,b5,b8);
node sp1=node(b4,b3,b2,b1);
node sp2=node(b5,b6,b7,b8);
ll res1=used[x1];
ll res2=used[x2];
ll res3=used[x3];
ll res4=used[x4];
res1=res1-check(sp1,x1)-check(sp2,x1);
res2=res2-check(sp1,x2)-check(sp2,x2)-check(x1,x2);
res3=res3-check(sp1,x3)-check(sp2,x3)-check(x1,x3)-check(x2,x3);
res4=res4-check(sp1,x4)-check(sp2,x4)-check(x1,x4)-check(x2,x4)-check(x3,x4);
ans+=res1*res2*res3*res4;
//PF("{%lld %lld %lld %lld %lld}\n",used[x1],res1,check(sp1,x1),check(sp2,x1),res4);
}
int main(){
SF("%d",&n);
for(int i=1;i<=n;i++){
SF("%d%d%d%d",&t[i].a1,&t[i].a2,&t[i].a3,&t[i].a4);
solve(t[i].a4,t[i].a3,t[i].a2,t[i].a1);
solve(t[i].a3,t[i].a2,t[i].a1,t[i].a4);
solve(t[i].a2,t[i].a1,t[i].a4,t[i].a3);
solve(t[i].a1,t[i].a4,t[i].a3,t[i].a2);
}
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++){
count(t[i].a1,t[i].a2,t[i].a3,t[i].a4,t[j].a4,t[j].a3,t[j].a2,t[j].a1);
count(t[i].a1,t[i].a2,t[i].a3,t[i].a4,t[j].a3,t[j].a2,t[j].a1,t[j].a4);
count(t[i].a1,t[i].a2,t[i].a3,t[i].a4,t[j].a2,t[j].a1,t[j].a4,t[j].a3);
count(t[i].a1,t[i].a2,t[i].a3,t[i].a4,t[j].a1,t[j].a4,t[j].a3,t[j].a2);
}
PF("%lld",ans/3ll);
}