题意:
用1*2和2*1的两种地毯铺地 问有多少种情况
思路:
直接推转移方程
从An-1的地方只有1种转移方法
从An-2的地方有5种转移方法
n-3转移不到n
但是n-4可以 也是最复杂的
从An-4的地方有种(An-3 - An-4)转移方法
因为n-4是从红线的地方转移过来的
所以我们最后的转移方程就是
An = An-1 + 5*An-2 + An-3 - An-4
手推一下前4项 1 5 11 36
然后直接推矩阵写快速幂就行了
1 5 1 -1
1 0 0 0
0 1 0 0
0 0 1 0
坑点是因为有负数次幂 所以最后要+mod再%mod
最后附上快速幂模板
1 #include<bits/stdc++.h> 2 #define cl(a,b) memset(a,b,sizeof(a)) 3 #define debug(a) cerr<<#a<<"=="<<a<<endl 4 using namespace std; 5 typedef long long ll; 6 typedef pair<int,int> pii; 7 8 const int maxn=4; 9 const int mod=1e9+7; 10 11 struct matrix 12 { 13 ll a[maxn][maxn]; 14 int row,col; 15 matrix():row(maxn),col(maxn){cl(a,0);} 16 matrix(int x,int y):row(x),col(y){cl(a,0);} 17 void show() 18 { 19 for(int i=0; i<row; i++) 20 { 21 for(int j=0; j<col; j++) 22 { 23 printf("%d%c",a[i][j],j==col-1?' ':' '); 24 } 25 } 26 } 27 inline ll* operator [] (int x) 28 { 29 return a[x]; 30 } 31 inline matrix operator * (matrix x) 32 { 33 matrix tmp(row,col); 34 for (int i=0; i<row; i++) 35 for (int j=0; j<col; j++) 36 for (int k=0; k<row; k++) 37 tmp[i][j]=(tmp[i][j]+a[i][k]*x[k][j])%mod; 38 return tmp; 39 } 40 inline void operator *= (matrix x) 41 { 42 *this = *this * x; 43 } 44 matrix operator ^ (ll x) 45 { 46 matrix result(row,col),now=*this; 47 for(int i=0; i<row; i++) 48 { 49 result[i][i]=1; 50 } 51 while(x) 52 { 53 if(x%2) result*=now; 54 now*=now; 55 x/=2; 56 } 57 return result; 58 } 59 }; 60 61 int main() 62 { 63 ll n,a[4]= {1,5,11,36}; 64 while(~scanf("%lld",&n)) 65 { 66 if(n<=4) 67 { 68 printf("%lld ",a[n-1]); 69 } 70 else 71 { 72 matrix mt(4,4); 73 mt[0][0]=1,mt[0][1]=5,mt[0][2]=1,mt[0][3]=-1; 74 mt[1][0]=1,mt[2][1]=1,mt[3][2]=1; 75 mt=mt^(n-4); 76 ll ans=0; 77 ans+=((36*mt[0][0]+11*mt[0][1]+5*mt[0][2]+1*mt[0][3])%mod+mod)%mod; 78 printf("%lld ",ans); 79 } 80 } 81 return 0; 82 }/* 83 84 1 85 2 86 87 */