Covering
题意:一个4*n的矩形广场,要用2*1的瓷砖和1*2的瓷砖铺满,问有几种铺瓷砖的方案;
用1*2和2*1的瓷砖铺满2*n的广场,这道题的递推式是ans[n]=ans[n-1]+2*ans[n-2];
先写了个dfs找了n=1~10的结果:1, 5, 11, 36, 95, 281, 781, 2245, 6336, 18061;
1*5=5但5*5!=11;
2*5+1=11但2*11+5!=36;
36+11*5+5-1=95而且95+36*5+11-5=281
到此为止找到递推式ans[n]=ans[n-1]+5*ans[n-2]+ans[n-3]-ans[n-4];
找递推式的过程就是不断试验,在没有明显规律下,只能慢慢的试,运气好就对了,运气不好可能一直试不出来~~~
数据时1e18,所以想到用矩阵快速幂;构造一个矩阵A,使其满足下面式子
根据递推式和矩阵运算特点得出矩阵A:
矩阵A第一行是递推式的系数, 下边每行的1对应结果中ans[n-i]:根据第二行的运算得到ans[n-1], 第三行得到ans[n-2], 第四行得到ans[n-3];
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
long long n;
//注释部分是用来打表找递推式的程序;
//int vis[110][110];
//int ans, n;
//int ok(){
// for(int i=0; i<n; i++){
// if(vis[3][i]==0) return 0;
// }
// return 1;
//}
//void dfs(int x, int y){
// if(x==4){
// if(ok()){
// ans++;
// }
// return;
// }
// if(y==n) dfs(x+1, 0);
// if(y>n) return;
// if(vis[x][y]) dfs(x, y+1);
// else{
// if(y+1<n&&vis[x][y+1]==0&&vis[x][y]==0){
// vis[x][y]=vis[x][y+1]=1;
// dfs(x, y+2);
// vis[x][y]=vis[x][y+1]=0;
// }
// if(x+1<4&&vis[x+1][y]==0&&vis[x][y]==0){
// vis[x][y]=vis[x+1][y]=2;
// dfs(x, y+1);
// vis[x][y]=vis[x+1][y]=0;
// }
// }
//}
struct node{
long long a[5][5];
};
const long long mod=1e9+7;
node mul(node x, node y){
node z;
memset(z.a, 0, sizeof(z.a));
for(int i=0; i<4; i++){
for(int j=0; j<4; j++){
for(int k=0; k<4; k++)
z.a[i][j]+=x.a[i][k]*y.a[k][j];
z.a[i][j]%=mod;
}
}
return z;
}
node _pow(node x, node y, long long p){
node z;
memset(z.a, 0, sizeof(z.a));
for(int i=0; i<4; i++){
z.a[i][i]=1;
}
while(p){
if(p&1){
z=mul(z, x);
}
x=mul(x, x);
p>>=1;
}
z=mul(z, y);
return z;
}
int main(){
// while(cin >> n){
// memset(vis, 0, sizeof(vis));
// ans=0;
// dfs(0, 0);
// cout << "-------" << ans << endl;
// }
while(~scanf("%lld", &n)){
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 {
node x;
memset(x.a, 0, sizeof(x.a));
x.a[0][0]=1;
x.a[0][1]=5;
x.a[0][2]=1;
x.a[0][3]=-1;
x.a[1][0]=1;
x.a[2][1]=1;
x.a[3][2]=1;
node y;
memset(y.a, 0, sizeof(y.a));
y.a[0][0]=36;
y.a[1][0]=11;
y.a[2][0]=5;
y.a[3][0]=1;
node z;
z=_pow(x, y, n-4);
printf("%lld\n", (z.a[0][0]+mod)%mod);
}
}
return 0;
}