arc062 E - Building Cubes with AtCoDeer

E - Building Cubes with AtCoDeer

计数题,首先当前砖块的情况可以压缩成1个long long表示,考虑处理出每个砖块旋转同构的所有情况中,压缩后数字最小的那个作为该砖块权值。

然后枚举顶面与下底面i,j (i < j),然后枚举下底面相对顶面的旋转情况,再考察插入四周四个面,注意四周面可能是四色相同或者对角相同,需要额外统计。

这样显然一种可行方案被统计3次,最后答案除以3即可。

#include
#define pii pair
#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
#define VLL vector
#define pll pair
#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
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

map 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 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 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();
}

你可能感兴趣的:(刷题集,c++,拓扑学,算法,题解)