hihocoder第42周 k*N骨牌覆盖(状态dp+矩阵快速幂)

上周的3*N的骨牌,因为状态只有8中,所以我们可以手算出状态转移的矩阵

但是这周是k*N,状态矩阵不好手算,都是我们改成用程序自动生成一个状态转移的矩阵就行了,然后用这个矩阵进行快速幂即可

枚举枚举上下两行的状态,然后判断上一行的状态能不能转移为这一行的状态

如果上一行的某个位置为0,那么这一行的该位置必须为1

如果上一行的某个位置为1,那么这一行的该位置可以为0

如果上一行的某个位置为1,且这一行的该位置为1, 那么上下两行该位置相邻的位置也得为1

根据这三条规则判断状态能不能转移成功,然后生成矩阵

因为状态矩阵很大,不能够开成局部变量,所以一律开成全局的,函数的返回值全部改成void

  1 #include <stdio.h>

  2 #include <string.h>

  3 #include <stdlib.h>

  4 #include <algorithm>

  5 #include <iostream>

  6 #include <queue>

  7 #include <stack>

  8 #include <vector>

  9 #include <map>

 10 #include <set>

 11 #include <string>

 12 #include <math.h>

 13 using namespace std;

 14 #pragma warning(disable:4996)

 15 typedef long long LL;

 16 const int INF = 1 << 30;

 17 const int MOD = 12357;

 18 const int N = 1 << 8;

 19 int n, k;

 20 struct Matrix

 21 {

 22     int mat[N][N];

 23     void makeUnit()

 24     {

 25         int m = (1 << k);

 26         for (int i = 0; i < m; ++i)

 27         {

 28             for (int j = 0; j < m; ++j)

 29                 mat[i][j] = (i == j);

 30         }

 31     }

 32     void makeZero()

 33     {

 34         int m = 1 << k;

 35         for (int i = 0; i < m; ++i)

 36         {

 37             for (int j = 0; j < m; ++j)

 38                 mat[i][j] = 0;

 39         }

 40     }

 41 }a, ret1, ret2;

 42 void copy(Matrix &des, const Matrix &s)

 43 {

 44     int m = 1 << k;

 45     for (int i = 0; i < m; ++i)

 46     {

 47         for (int j = 0; j < m; ++j)

 48             des.mat[i][j] = s.mat[i][j];

 49     }

 50 }

 51 void dfs(int x, int y, int col)//这个题目提示的矩阵生成方法,挺厉害的

 52 {

 53     if (col == k)

 54     {

 55         a.mat[y][x] = 1;

 56         return;

 57     }

 58     dfs(x << 1, y << 1 | 1, col + 1);

 59     dfs(x << 1 | 1, y << 1, col + 1);

 60     if (col + 2 <= k)

 61         dfs((x << 2) + 3, (y << 2) + 3, col + 2);

 62 }

 63 void multiply(const Matrix &lhs, const Matrix &rhs)

 64 {

 65     ret2.makeZero();

 66     int m = 1 << k;

 67     for (int z = 0; z < m; ++z)

 68     {

 69         for (int i = 0; i < m; ++i)

 70         {

 71             if (lhs.mat[i][z] == 0) continue;

 72             for (int j = 0; j < m; ++j)

 73             {

 74                 ret2.mat[i][j] += lhs.mat[i][z] * rhs.mat[z][j];

 75                 if (ret2.mat[i][j] >= MOD)

 76                     ret2.mat[i][j] %= MOD;

 77             }

 78         }

 79     }

 80 }

 81 void pow(Matrix a, int t)

 82 {

 83     ret1.makeUnit();

 84     while (t)

 85     {

 86         if (t & 1)

 87         {

 88             multiply(ret1, a);

 89             copy(ret1, ret2);

 90         }

 91         t >>= 1;

 92         multiply(a, a);

 93         copy(a, ret2);

 94     }

 95 }

 96 bool check(int x, int y)

 97 {

 98     int m = 1 << k-1;

 99     while (m)

100     {

101         if ((x & 1) == 0 && (y & 1) == 1)

102         {

103             x >>= 1;

104             y >>= 1;

105             m >>= 1;

106         }

107         else if ((x & 1) == 1 && (y & 1) == 0)

108         {

109             x >>= 1;

110             y >>= 1;

111             m >>= 1;

112         }

113         else if ((x & 1) == 1 && (y & 1) == 1)

114         {

115             x >>= 1;

116             y >>= 1;

117             if ((x & 1) == 1 && (y & 1) == 1)

118             {

119                 x >>= 1;

120                 y >>= 1;

121                 m >>= 2;

122             }

123             else

124                 return false;

125         }

126         else

127             return false;

128     }

129     return true;

130 }

131 void makeMatrix()

132 {

133     int m = 1 << k;

134     for (int i = 0; i < m; ++i)

135     {

136         for (int j = 0; j < m; ++j)

137         {

138             if (check(i, j))

139                 a.mat[i][j] = 1;

140         }

141     }

142 }

143 int main()

144 {

145     scanf("%d%d", &k, &n);

146     a.makeZero();

147     //dfs(0, 0, 0);

148     makeMatrix();

149     pow(a, n);

150     int m = (1 << k) - 1;

151     printf("%d\n", ret1.mat[m][m]);

152     return 0;

153 }
View Code

 

你可能感兴趣的:(code)