CSU 1027 Smallbox魔方

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;
}
原文地址:https://www.cnblogs.com/staginner/p/2511049.html