您的位置:首页 > 其它

CSU 1027 Smallbox魔方

2012-05-21 00:44 399 查看
CSU_1027

对于一个立方体,一共有24种本质不同的旋转,整体上分为四类:

①静止不动;

②以某面与对面的中心的连线为轴,沿一个方向旋转90度、180度、270度;

③以某棱与对棱的中心的连线为轴,沿一个方向旋转180度;

④以某个顶点与对顶点的连线为轴,沿一个方向旋转60度、120度。

对于每类都可以用组合数计算出不动方案的种数,然后应用一下burnside引理就可以得到最后的结果了。

#include<stdio.h>
#include<string.h>
#define MAXD 15010
#define MOD 1000000007
int N, M, a[10], b[10], ny[MAXD];
long long exgcd(long long a, long long b, long long &x, long long &y)
{
if(b == 0)
x = 1, y = 0;
else
exgcd(b, a % b, y, x), y -= x * (a / b);
}
void prepare()
{
int i;
long long x, y;
for(i = 1; i <= 15000; i ++)
{
exgcd(i, MOD, x, y);
x = (x % MOD + MOD) % MOD;
ny[i] = x;
}
}
void init()
{
int i;
scanf("%d", &N);
M = 6 * N * N;
for(i = 0; i < 6; i ++)
scanf("%d", &a[i]);
}
long long comb(int n, int m)
{
int i;
long long ans = 1;
for(i = n - m + 1; i <= n; i ++)
ans = ans * i % MOD;
for(i = 2; i <= m; i ++)
ans = ans * ny[i] % MOD;
return ans;
}
long long calculate(int m)
{
int i, j, n = 0;
long long ans = 1;
for(i = 0; i < 6; i ++)
{
if(b[i] % m != 0)
return 0;
b[i] /= m;
n += b[i];
}
for(i = 0; i < 6; i ++)
{
ans = ans * comb(n, b[i]) % MOD;
n -= b[i];
}
return ans;
}
long long frotate()
{
int i, j;
long long ans = 0;
// 0
memcpy(b, a, sizeof(a));
ans = (ans + calculate(1)) % MOD;
// 90 270
if(N & 1)
{
for(i = 0; i < 6; i ++)
for(j = 0; j < 6; j ++)
{
memcpy(b, a, sizeof(a));
-- b[i], -- b[j];
if(b[i] < 0 || b[j] < 0)
continue;
ans = (ans + 6 * calculate(4)) % MOD;
}
}
else
{
memcpy(b, a, sizeof(a));
ans = (ans + 6 * calculate(4)) % MOD;
}
// 180
if(N & 1)
{
for(i = 0; i < 6; i ++)
for(j = 0; j < 6; j ++)
{
memcpy(b, a, sizeof(a));
-- b[i], -- b[j];
if(b[i] < 0 || b[j] < 0)
continue;
ans = (ans + 3 * calculate(2)) % MOD;
}
}
else
{
memcpy(b, a, sizeof(a));
ans = (ans + 3 * calculate(2)) % MOD;
}
return ans;
}
long long erotate()
{
int i;
long long ans = 0;
// 180
memcpy(b, a, sizeof(a));
ans = (6 * calculate(2)) % MOD;
return ans;
}
long long vrotate()
{
int i;
long long ans = 0;
// 60 120
memcpy(b, a, sizeof(a));
ans = (8 * calculate(3)) % MOD;
return ans;
}
void solve()
{
long long ans = 0;
ans = (ans + frotate()) % MOD;
ans = (ans + erotate()) % MOD;
ans = (ans + vrotate()) % MOD;
ans = ans * ny[24] % MOD;
printf("%lld\n", ans);
}
int main()
{
int t;
prepare();
scanf("%d", &t);
while(t --)
{
init();
solve();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: