题目:用 1×1×1, 1× 2×1以及2×1×1的三种木块(横绿竖蓝,且绿蓝长度均为2),
搭建高长宽分别为K × 2^N × 1的墙,不能翻转、旋转(其中,0<=N<=1024,1<=K<=4)
有多少种方案,输出结果
对1000000007取模。举个例子如给定高度和长度:N=1 K=2,则 答案是7,即有7种搭法,如下图所示:
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
/*
木块砌墙
*/
#ifdef WIN32
#define ll __int64
#else
#define ll long long
#endif
// 1 covered 0 uncovered
void cal(int a[6][32][32],int n,int col,int laststate,int nowstate) {
if (col >= n) {
++a[n][laststate][nowstate];
return;
}
//不填 或者用1*1的填
cal(a,n, col + 1, laststate, nowstate);
if (((laststate >> col) & 1) == 0) {
cal(a,n, col + 1, laststate, nowstate | (1 << col));
if ((col + 1 < n) && (((laststate >> (col + 1)) & 1) == 0)) {
cal(a,n, col + 2, laststate, nowstate);
}
}
}
inline int mul(ll x, ll y) {
return x * y % 1000000007;
}
void multiply(int n,int a[][32],int b[][32]) { // b = a * a
int i,j, k;
for (i = 0; i < n; ++i) {
for (j = 0; j < n; ++j) {
for (k = b[i][j] = 0; k < n; ++k) {
if ((b[i][j] += mul(a[i][k],a[k][j])) >= 1000000007) {
b[i][j] -= 1000000007;
}
}
}
}
}
int calculate(int n,int k) {
int i, j;
int a[6][32][32],mat[2][32][32];
memset(a,0,sizeof(a));
for (i = 1; i <= 5; ++i) {
for (j = (1 << i) - 1; j >= 0; --j) {
cal(a,i, 0, j, 0);
}
}
memcpy(mat[0], a[k],sizeof(mat[0]));
k = (1 << k);
for (i = 0; n; --n) {
multiply(k, mat[i], mat[i ^ 1]);
i ^= 1;
}
return mat[i][0][0];
}
int main()
{
cout<<calculate(1,2);
}