当前位置:   article > 正文

15年国赛 铺瓷砖_[蓝桥杯 2015 国 a] 铺瓷砖

[蓝桥杯 2015 国 a] 铺瓷砖

标题:铺瓷砖

为了让蓝桥杯竞赛更顺利的进行,主办方决定给竞赛的机房重新铺放瓷砖。机房可以看成一个n*m的矩形,而这次使用的瓷砖比较特别,有两种形状,如【图1.png】所示。在铺放瓷砖时,可以旋转。
 
主办方想知道,如果使用这两种瓷砖把机房铺满,有多少种方案。

【输入格式】
输入的第一行包含两个整数,分别表示机房两个方向的长度。

【输出格式】
输出一个整数,表示可行的方案数。这个数可能很大,请输出这个数除以65521的余数。

【样例输入1】
4 4
【样例输出1】
2
【样例说明1】
这两种方案如下【图2.png】所示:
 
【样例输入2】
2 6
【样例输出2】
4
【数据规模与约定】
对于20%的数据,1<=n, m<=5。
对于50%的数据,1<=n<=100,1<=m<=5。
对于100%的数据,1<=n<=10^15,1<=m<=6。
 
资源约定:
峰值内存消耗(含虚拟机) < 512M
CPU消耗  < 8000ms

求解使用两种瓷砖铺满一个n*m的区域的方案数。
对于小范围的数据,可以使用搜索求解。也可以使用搜索在自己的电脑上先算出方案数,将这些答案保存在程序中,直接输出答案即可。
对于稍微大一点的数据,可以使用状态压缩的动态规划来求解。有两种瓷砖,状态的转移比较复杂,
对于100%的数据,需要将在状态压缩的动态规划中去除无用状态,然后建立矩阵表示,使用矩阵乘法的方法来实现状态压缩中的递推。

  1. //瓷砖铺放
  2. #include <iostream>
  3. #include <cstdlib>
  4. #include <cstdio>
  5. #include <cstring>
  6. using namespace std;
  7. const int MOD = 65521;
  8. const int MM = 800;
  9. const int RSIZE = 128;
  10. const int MATRIX_SIZE = 256;
  11. class Matrix {
  12. public:
  13. unsigned int s[MATRIX_SIZE][MATRIX_SIZE];
  14. };
  15. long long n;
  16. int m, M;
  17. int tt[MM][RSIZE], fr[MM][RSIZE];
  18. int *cur[MM], *curFr[MM];
  19. int tc[MM], nc[MM];
  20. Matrix tm, dst, tmpm;
  21. bool mark[MM], canReach[MM];
  22. int remap[MM], who[MM];
  23. void search(int cp, int cl, int nl)
  24. {
  25. if (cp > m)
  26. return ;
  27. if (cp == m)
  28. {
  29. *(cur[cl]++) = nl;
  30. *(curFr[nl]++) = cl;
  31. return ;
  32. }
  33. search(cp+1, cl*3+1, nl*3);
  34. search(cp+1, cl*3+2, nl*3+1);
  35. // (1)
  36. search(cp+2, cl*3*3+1, nl*3*3+3+1);
  37. search(cp+3, cl*3*3*3, nl*3*3*3+9+3+1);
  38. search(cp+4, cl*3*3*3*3, nl*3*3*3*3+27+9+3);
  39. // (2)
  40. search(cp+2, cl*3*3, nl*3*3+1);
  41. // (3)
  42. search(cp+2, cl*3*3, nl*3*3+3);
  43. // (4)
  44. if (cp>0 && nl%3==0)
  45. search(cp+1, cl*3, nl*3+3+1);
  46. // (5)
  47. search(cp+2, cl*3*3+1, nl*3*3+3*2+1);
  48. search(cp+3, cl*3*3*3, nl*3*3*3+9*2+3+1);
  49. search(cp+4, cl*3*3*3*3, nl*3*3*3*3+27*2+9+3);
  50. // (6)
  51. search(cp+3, cl*3*3*3, nl*3*3*3+3);
  52. // (7)
  53. if (cp>0 && nl%3==0)
  54. search(cp+1, cl*3, nl*3+3+2);
  55. // (8)
  56. if (cp>0 && nl%3==0)
  57. {
  58. search(cp+2, cl*3*3+1, nl*3*3+9+3+1);
  59. search(cp+3, cl*3*3*3, nl*3*3*3+27+9+3+1);
  60. search(cp+4, cl*3*3*3*3, nl*3*3*3*3+81+27*2+9+3);
  61. }
  62. }
  63. void goto0(int x)
  64. {
  65. if (canReach[x])
  66. return ;
  67. canReach[x] = true;
  68. for (int *pp = fr[x]; pp < curFr[x]; ++pp)
  69. goto0(*pp);
  70. }
  71. int ccnt = 0;
  72. void go(int x)
  73. {
  74. if (!canReach[x])
  75. return ;
  76. if (mark[x])
  77. return ;
  78. who[ccnt] = x;
  79. remap[x] = ccnt++;
  80. mark[x] = true;
  81. for (int *pp = tt[x]; pp < cur[x]; ++pp)
  82. go(*pp);
  83. }
  84. void pr3(int x, int w)
  85. {
  86. if (w > 1)
  87. pr3(x/3, w-1);
  88. cout << x%3;
  89. }
  90. void prepare()
  91. {
  92. memset(tt, 0, sizeof(tt));
  93. for (int i = 0; i < M; ++i)
  94. {
  95. cur[i] = tt[i];
  96. curFr[i] = fr[i];
  97. }
  98. search(0, 0, 0);
  99. int maxR = 0;
  100. for (int i = 0; i < M; ++i)
  101. if (cur[i]-tt[i] > maxR)
  102. maxR = cur[i] - tt[i];
  103. maxR = 0;
  104. for (int i = 0; i < M; ++i)
  105. if (curFr[i]-fr[i] > maxR)
  106. maxR = curFr[i] - fr[i];
  107. memset(canReach, 0, sizeof(canReach));
  108. goto0(0);
  109. memset(mark, 0, sizeof(mark));
  110. go(0);
  111. memset(&tm, 0, sizeof(tm));
  112. for (int i = 0; i < M; ++i)
  113. if (mark[i])
  114. for (int *pp = tt[i]; pp < cur[i]; ++pp)
  115. if (mark[*pp])
  116. tm.s[remap[i]][remap[*pp]]++;
  117. }
  118. void matrixMul(Matrix &dst, const Matrix &a, const Matrix &b)
  119. {
  120. for (int i = 0; i < ccnt; ++i)
  121. for (int j = 0; j < ccnt; ++j)
  122. {
  123. long long r = 0;
  124. const unsigned int *ai = a.s[i];
  125. for (int k = 0; k < ccnt; ++k)
  126. r += ai[k] * b.s[k][j];
  127. r %= MOD;
  128. dst.s[i][j] = r;
  129. }
  130. }
  131. long long getAns()
  132. {
  133. long long cur = 1;
  134. memset(&dst, 0, sizeof(dst));
  135. for (int i = 0; i < ccnt; ++i)
  136. dst.s[i][i] = 1;
  137. while (n)
  138. {
  139. if (n&cur)
  140. {
  141. matrixMul(tmpm, dst, tm);
  142. dst = tmpm;
  143. n -= cur;
  144. }
  145. matrixMul(tmpm, tm, tm);
  146. tm = tmpm;
  147. cur *= 2;
  148. }
  149. return dst.s[0][0];
  150. }
  151. int main()
  152. {
  153. cin >> n >> m;
  154. M = 1;
  155. for (int i = 0; i < m; ++i)
  156. M *= 3;
  157. prepare();
  158. cout << getAns() << endl;
  159. return 0;
  160. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/64387
推荐阅读
相关标签
  

闽ICP备14008679号