题意:在4*n的地板上铺1*2 或 2*1的瓷砖,在不重叠的前提下,问共有多少种铺满的方式?
思路:n的范围很大很大,所以肯定是个规律题,用dfs把前几组的答案找出来,1,5,11,36,95,281,2245,6336,18063,只凭肉眼观察很难找出规律来,猜测是线性递推方程,假设 f(n)=af(n-1) +bf(n-2),利用高斯消元发现结果不是整数,高斯消元实际上就是线性代数上学的求解线性方程组,当我们试到f(n)=af(n-1) +bf(n-2) + cf(n-3)+df(n-4)时发现存在正数解,之后就简单了,利用矩阵快速幂求解。
高斯消元,网上找得模板,有了这个,给你任意一组数,都可以出线性递推关系了,前提是存在这个关系
//f(n)=f(n-1)*a+f(n-2)*b+f(n-3)*c+f(n-4)*d情况下的高斯消元
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int maxn=105;
typedef double Matrix[maxn][maxn];
Matrix A,S;
//n是方程的个数
void gauss(Matrix A,int n)
{
int i,j,k,r;
for(int i=0; ifabs(A[r][i]))r=j;
if(r!=i)
for(j=0; j<=n; j++)swap(A[r][j],A[i][j]);
for(k=i+1; k=0; i--)
{
for(j=i+1; j
#include
#include
const int MOD = 1000000007;
typedef long long ll;
struct Matrix
{
ll A[4][4];
};
Matrix mul(Matrix A,Matrix B)
{
Matrix C;
memset(C.A,0,sizeof(C.A));
for(int i = 0; i < 4; i++) {
for(int j = 0; j < 4; j++) {
for(int k = 0; k < 4; k++) {
C.A[i][j] = (C.A[i][j] % MOD + A.A[i][k] * B.A[k][j] + MOD) % MOD;
}
}
}
return C;
}
Matrix q_pow(Matrix A,ll n)
{
Matrix ans;
memset(ans.A,0,sizeof(ans.A));
for(int i = 0; i < 4; i++) {
ans.A[i][i] = 1;
}
while(n) {
if(n & 1) {
ans = mul(ans,A);
}
A = mul(A , A);
n >>= 1;
}
return ans;
}
int main(void)
{
Matrix base,B;
base.A[0][0] = 1,base.A[0][1] = 5,base.A[0][2] = 1,base.A[0][3] = -1;
base.A[1][0] = 1,base.A[1][1] = 0,base.A[1][2] = 0,base.A[1][3] = 0;
base.A[2][0] = 0,base.A[2][1] = 1,base.A[2][2] = 0,base.A[2][3] = 0;
base.A[3][0] = 0,base.A[3][1] = 0,base.A[3][2] = 1,base.A[3][3] = 0;
B.A[0][0] = 36,B.A[1][0] = 11,B.A[2][0] = 5,B.A[3][0] = 1;
ll n;
while(scanf("%I64d",&n) != EOF) {
if(n == 1) printf("1\n");
else if(n == 2) printf("5\n");
else if(n == 3) printf("11\n");
else if(n == 4) printf("36\n");
else {
Matrix ans = q_pow(base,n - 4);
ans = mul(ans,B);
printf("%I64d\n",(ans.A[0][0] + MOD) % MOD);
}
}
}