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;

}

 

你可能感兴趣的:(BO)