HDOJ 3547 DIY Cube 解题报告

题目链接: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
  1 #include <cstdio>
  2 typedef long long LL;
  3 #define Mod 10000000000000000LL
  4 
  5 const int Base[4] = {0, 1, 2, 112};
  6 const LL Ans[4] = {0LL, 23LL, 296LL, 2675058176LL};
  7 
  8 struct Frac
  9 {
 10     LL fz, fm;
 11     Frac (LL _fz = 0LL, LL _fm = 0LL) {fz = _fz, fm = _fm;}
 12     LL Abs(LL x)
 13     {
 14         return x > 0 ? x : -x;
 15     }
 16     LL gcd(LL x, LL y)
 17     {
 18         return !y ? x : gcd(y, x % y);
 19     }
 20     void Simplify()
 21     {
 22         LL d = gcd(Abs(fz), Abs(fm));
 23         fz /= d, fm /= d;
 24         if (fm < 0) fm = -fm, fz = -fz;
 25     }
 26     Frac operator + (const Frac a)
 27     {
 28         Frac b;
 29         b.fz = fz * a.fm + fm * a.fz;
 30         b.fm = fm * a.fm;
 31         b.Simplify();
 32         return b;
 33     }
 34     Frac operator - (const Frac a)
 35     {
 36         Frac b;
 37         b.fz = fz * a.fm - fm * a.fz;
 38         b.fm = fm * a.fm;
 39         b.Simplify();
 40         return b;
 41     }
 42     Frac operator * (const Frac a)
 43     {
 44         Frac b;
 45         b.fz = fz * a.fz;
 46         b.fm = fm * a.fm;
 47         b.Simplify();
 48         return b;
 49     }
 50     Frac operator / (const Frac a)
 51     {
 52         Frac b;
 53         b.fz = fz * a.fm;
 54         b.fm = fm * a.fz;
 55         b.Simplify();
 56         return b;
 57     }
 58     void out()
 59     {
 60         printf("%lld/%lld\n", fz, fm);
 61     }
 62 }X[5][5], Y[5];
 63 
 64 inline void Gauss()
 65 {
 66     for (int i = 1; i < 3; i ++)
 67         for (int j = i + 1; j <= 3; j ++)
 68         {
 69             Frac t = X[j][i] / X[i][i];
 70             for (int k = i; k <= 3; k ++)
 71                 X[j][k] = X[j][k] - X[i][k] * t;
 72             Y[j] = Y[j] - Y[i] * t;
 73         }
 74     for (int i = 3; i; i --)
 75     {
 76         Frac sum;
 77         sum.fz = 0LL, sum.fm = 1LL;
 78         for (int j = i + 1; j <= 3; j ++)
 79             sum = sum + X[i][j] * Y[j];
 80         Y[i] = (Y[i] - sum) / X[i][i];
 81     }
 82 }
 83 
 84 int main()
 85 {
 86     for (int i = 1; i <= 3; i ++)
 87     {
 88         for (int j = 3; j; j --)
 89         {
 90             if (j == 3) X[i][j].fz = Base[i];
 91                 else X[i][j].fz = X[i][j + 1].fz * X[i][j + 1].fz;
 92             X[i][j].fm = 1LL;
 93         }
 94         Y[i].fz = Ans[i], Y[i].fm = 1LL;
 95     }
 96     Gauss();
 97     for (int i = 1; i <= 3; i ++)
 98         Y[i].out();
 99     return 0;
100 }
HDOJ 3547 (Gauss)

 

转载于:https://www.cnblogs.com/gromah/p/5767013.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值