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; }