E - Building Cubes with AtCoDeer
计数题,首先当前砖块的情况可以压缩成1个long long表示,考虑处理出每个砖块旋转同构的所有情况中,压缩后数字最小的那个作为该砖块权值。
然后枚举顶面与下底面i,j (i < j),然后枚举下底面相对顶面的旋转情况,再考察插入四周四个面,注意四周面可能是四色相同或者对角相同,需要额外统计。
这样显然一种可行方案被统计3次,最后答案除以3即可。
#include<bits/stdc++.h>
#define pii pair<int,int>
#define fi first
#define sc second
#define pb push_back
#define ll long long
#define trav(v,x) for(auto v:x)
#define all(x) (x).begin(), (x).end()
#define VI vector<int>
#define VLL vector<ll>
#define pll pair<ll, ll>
#define double long double
//#define int long long
using namespace std;
const int N = 1e6 + 100;
const int inf = 1e9;
//const ll inf = 1e18;
#ifdef LOCAL
void debug_out(){cerr << endl;}
template<typename Head, typename... Tail>
void debug_out(Head H, Tail... T)
{
cerr << " " << to_string(H);
debug_out(T...);
}
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
#else
#define debug(...) 42
#endif
#define node array<int, 4>
map<ll, ll> cnt;
ll cal_val(node x)
{
ll nw = 0;
for(int i = 0; i < 4; i++)
{
nw = nw * 1000LL + x[i];
}
return nw;
}
node rot(node x)
{
node y;
for(int i = 0; i < 4; i++)
y[i] = x[(i + 1) % 4];
return y;
}
ll cal_id(node x)
{
ll mn = 1e18;
for(int i = 0; i < 4; i++)
{
ll nw = cal_val(x);
mn = min(mn, nw);
x = rot(x);
}
return mn;
}
void add(node x, int y)
{
ll id = cal_id(x);
cnt[id] += y;
}
ll ffac(ll x, int y)
{
ll res = 1;
for(ll i = 0; i < y; i++)
res = res * (x - i);
return res;
}
void sol()
{
int n;
cin >> n;
vector<node> a(n);
for(int i = 0; i < n; i++)
{
int x, y, z, t;
cin >> x >> y >> z >> t;
a[i] = {x, y, z, t};
add(a[i], 1);
}
ll ans = 0;
for(int i = 0; i < n; i++)
{
//cerr << "!!!!!" << i << ' ' << cnt[cal_id(a[i])] << '\n';
add(a[i], -1);
for(int r = 0; r < 4; r++)
{
for(int j = i + 1; j < n; j++)
{
map<ll, int> need;
add(a[j], -1);
swap(a[j][1], a[j][3]);
ll res = 1;
for(int face = 0; face < 4; face++)
{
//cerr << i << ' ' << r << ' ' << j << ' ' << face << '\n';
node nw;
nw[0] = a[i][face];
nw[1] = a[i][(face + 3) % 4];
nw[2] = a[j][(face + 3) % 4];
nw[3] = a[j][face];
// cerr << nw[0] << ' ' << nw[1] << ' ' << nw[2] << ' ' << nw[3] << '\n';
// system("pause");
if(nw[0] == nw[1] && nw[1] == nw[2] && nw[2] == nw[3])
res = res * 4;
else if(nw[0] == nw[2] && nw[1] == nw[3])
res = res * 2;
need[cal_id(nw)]++;
}
trav(v, need)
{
res = res * ffac(cnt[v.fi], v.sc);
}
ans = (ans + res);
swap(a[j][1], a[j][3]);
add(a[j], 1);
}
a[i] = rot(a[i]);
}
add(a[i], 1);
//cerr << "!!!??" << i << ' ' << cnt[cal_id(a[i])] << '\n';
}
cout << ans / 3 << '\n';
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
// int tt;
// cin >> tt;
// while(tt--)
sol();
}