题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3547

题目大意:求用$C$种颜色给立方体的8个顶点染色的本质不同的方法。两种方法本质不同即不能通过旋转立方体使得两个立方体的染色情况一致。

简要题解:首先可以得到有24种组合旋转方式。根据Polya定理以及群论中的拉格朗日定理,然后再自己多想一想,就可以得到:$Ans=\frac{x^8+Ax^4+Bx^2+Cx}{24}$,可知有3个未知数,然后样例正好有3组数据,所以可以解方程解得$A=17,B=6,C=0$。注意第三个数据是模了$10^{15}$次方的,但是显然$112^4$的四次方并不会超过$10^{15}$,所以也可以拿来使用。最后直接高精度就可以了。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 using namespace std;
  5 #define K 10
  6 #define D 15
  7 
  8 const int T[5] = {0, 0, 6, 17, 1};
  9 int Case, n;
 10 
 11 struct Big
 12 {
 13     int len, num[101];
 14     Big () {len = 0; memset(num, 0, sizeof(num));}
 15     void init(int k)
 16     {
 17         len = 0;
 18         memset(num, 0, sizeof(num));
 19         for (; k; k /= K)
 20             num[++ len] = k % K;
 21         len = max(len, 1);
 22     }
 23     void Add(Big a)
 24     {
 25         len = max(len, a.len);
 26         for (int i = 1; i <= len; i ++)
 27             num[i] += a.num[i];
 28         for (int i = 1; i < len; i ++)
 29             if (num[i] >= K)
 30             {
 31                 num[i + 1] ++;
 32                 num[i] -= K;
 33             }
 34         if (num[len] >= K)
 35         {
 36             num[len + 1] = 1;
 37             num[len ++] -= K;
 38         }
 39     }
 40     void Times(Big a)
 41     {
 42         Big b;
 43         b.len = len + a.len - 1;
 44         for (int i = 1; i <= len; i ++)
 45             for (int j = 1; j <= a.len; j ++)
 46                 b.num[i + j - 1] += num[i] * a.num[j];
 47         for (int i = 1; i < b.len; i ++)
 48             if (b.num[i] >= K)
 49             {
 50                 b.num[i + 1] += b.num[i] / K;
 51                 b.num[i] %= K;
 52             }
 53         while (b.num[b.len] >= K)
 54         {
 55             b.num[b.len + 1] += b.num[b.len] / K;
 56             b.num[b.len ++] %= K;
 57         }
 58         len = b.len;
 59         for (int i = 1; i <= len; i ++)
 60             num[i] = b.num[i];
 61     }
 62     void Multi(int k)
 63     {
 64         for (int i = 1; i <= len; i ++)
 65             num[i] *= k;
 66         for (int i = 1; i < len; i ++)
 67             if (num[i] >= K)
 68             {
 69                 num[i + 1] += num[i] / K;
 70                 num[i] %= K;
 71             }
 72         while (num[len] >= K)
 73         {
 74             num[len + 1] += num[len] / K;
 75             num[len ++] %= K;
 76         }
 77     }
 78     void Divide(int k)
 79     {
 80         for (int i = len; i >= 1; i --)
 81         {
 82             if (i > 1) num[i - 1] += (num[i] % k) * K;
 83             num[i] /= k;
 84         }
 85         for (; !num[len] && len > 1; len --) ;
 86     }
 87     void out()
 88     {
 89         for (int i = min(D, len); i; i --)
 90             printf("%d", num[i]);
 91         puts("");
 92     }
 93 }A[5], Ans;
 94 
 95 int main()
 96 {
 97     scanf("%d", &Case);
 98     for (int Test = 1; Test <= Case; Test ++)
 99     {
100         scanf("%d", &n);
101         A[1].init(n), Ans.init(0);
102         for (int i = 2; i <= 4; i ++)
103         {
104             A[i] = A[i - 1];
105             A[i].Times(A[i - 1]);
106             A[i].Multi(T[i]);
107             Ans.Add(A[i]);
108             A[i].Divide(T[i]);
109         }
110         Ans.Divide(24);
111         printf("Case %d: ", Test);
112         Ans.out();
113     }
114     return 0;
115 }
HDOJ 3547

相关文章: