HDU 5434 矩阵快速幂

HDU 5434
题目链接:
http://www.bnuoj.com/v3/problem_show.php?pid=50239
题意:
有m*n矩阵,在上面放小象。
小象有攻击范围,为它的对角线所对应的四个单元格。但是小象有合成象的说法,即两个小象边相邻时会发生攻击范围的改变。
问有多少种放置小象的方案,使得小象之间不会相互攻击。
思路:
一种模型题,类似LightOj1332.求出关系后用矩阵快速幂递推。
这题是用合法性来递推的。枚举第一条的状态和第二条状态,看两条是否能够配上就可以。然后会得到一个关系矩阵,问题就解决了。
源码:
···

include

include

include

include

include

include

include

using namespace std;
const int MAXN = 1 << 7;

define LL long long

define mod (1000000007)

struct Matrix
{
LL d[MAXN][MAXN];
int len;
Matrix(){memset(d, 0, sizeof(d));}
void init(int _len){for(int i = 0 ; i < _len ; i++) d[i][i] = 1; len = _len;}
Matrix operator *(const Matrix &rbs)const{
Matrix ans;
ans.len = len;
for(int i = 0 ; i < len ; i++) for(int k = 0 ; k < len ; k++) for(int j = 0 ; j < MAXN ; j++)
ans.d[i][j] = (ans.d[i][j] + d[i][k] * rbs.d[k][j] % mod ) % mod;
return ans;
}
}org;
Matrix ppow(Matrix a, int x, int m)
{
// printf(“x = %d\n”, x);
Matrix ans;
ans.init(1 << m);
for(int i = x ; i ; i >>= 1){
// printf(“i = %d\n”, i);
// system(“pause”);
if(i & 1) ans = (ans * a);
a = a * a;
}
return ans;
}
int g[MAXN][MAXN];
void init(int m)
{
memset(g, 0, sizeof(g));
int cnt = 0;
for(int i = 0 ; i < (1 << m) ; i++){
for(int j = 0 ; j < (1 << m) ; j++){
int ok = 1;
for(int k = 0 ; k < m ; k++){
// if(i == 2 && j == 1 && k == 0){
// printf(“1 << k = %d\n”, 1 << k);
// printf(“1 << k = %d, 1 << k & i = %d\n”, (1 << k) & j, (1 << k) & i);
// }
if((1 << k) & j){
if(((1 << k) & i) == 0){
// if(i == 5 && j == 2 && k == 1){
// printf(“first\n”);
// }
int temp = 0;
if(k > 0 && ((1 << (k - 1)) & i) && (((1 << (k - 1)) & j) == 0)) temp++;
if(k < m - 1 && ((1 << (k + 1)) & i) && (((1 << (k + 1)) & j)== 0)) temp++;
// if(i == 2 && j == 1 && k == 0){
// printf(“temp = %d\n”, temp);
// }
if(temp) ok = 0;
}
}
if(ok == 0) break;
}
// if(ok){
// printf(“i = %d, j = %d\n”, i, j);
// system(“pause”);
// }
if(ok == 0) cnt++;
g[i][j] = ok;
}
}
// printf(“cnt = %d\n”, cnt);
org.init(1 << m);
for(int i = 0 ; i < (1 << m) ; i++) for(int j = 0 ; j < (1 << m) ; j++) org.d[i][j] = g[i][j];
}
int main()
{
int n, m;
while(scanf(“%d%d”, &n, &m) != EOF){
init(m);
// for(int i = 0 ; i < (1 << m) ; i++){
// for(int j = 0 ; j < (1 << m) ; j++) printf(“%d “, g[i][j]);
// printf(“\n”);
// }
Matrix ans = ppow(org, n - 1, m);
LL res = 0;
for(int i = 0 ; i < (1 << m) ; i++)
for(int j = 0 ; j < (1 << m) ; j++)
res = (res + ans.d[i][j]) % mod;
// printf(“ans\n”);
// for(int i = 0 ; i < (1 << m) ; i++){
// for(int j = 0 ; j < (1 << m) ; j++){
// printf(“%I64d “, ans.d[i][j]);
// }
// printf(“\n”);
// }
printf(“%I64d\n”, res);
}
return 0;
}
···

你可能感兴趣的:(HDU 5434 矩阵快速幂)