Covering
To protect boys and girls from getting hurt when playing happily on the playground, rich boy Bob decided to cover the playground using his carpets.
Meanwhile, Bob is a mean boy, so he acquired that his carpets can not overlap one cell twice or more.
He has infinite carpets with sizes of 1×2 and 2×1 , and the size of the playground is 4×n .
Can you tell Bob the total number of schemes where the carpets can cover the playground completely without overlapping?
Each test case only contains one positive integer n in a line.
1≤n≤1018
1 2
1 5
题意:给一个4*n的矩形,用1*2的矩阵填满,问能有多少种填法
解题思路:把4当作列数,n当作行数。当第n行填满时,第(n+1)行会出现以下几种情况:
情况a为第n行刚好填满且没有突出到第(n + 1)行,即为所求答案,由图不难推出:
a[n] = a[n - 1] + b[n - 1] + c[n - 1] + dx[n - 1] + dy[n - 1]
b[n] = a[n - 1]
c[n] = a[n - 1] + e[n - 1]
dx[n] = a[n - 1] + dy[n - 1]
dy[n] = a[n - 1] + dx[n - 1]
e[n] = c[n - 1]
令d[n] = dx[n] + dy[n]
则 a[n] = a[n - 1] + b[n - 1] + c[n - 1] + d[n - 1]
b[n] = a[n - 1]
c[n] = a[n - 1] + e[n - 1]
d[n] = a[n - 1] * 2 + d[n - 1]
e[n] = c[n - 1]
根据这个构造出矩阵即可
推公式自己不是很擅长,这个过程是我盗的,原文链接为:http://blog.youkuaiyun.com/a664607530/article/details/77619554
最后能推出的公式为 f[n]=f[n-1]+5*f[n-2]+f[n-3]-f[n-4]
根据这一公式能推出需要构造的矩阵为:
1 5 1 -1 f[4]
1 0 0 0 * f[3]
0 1 0 0 f[2]
0 0 1 0 f[1]
f[4]=36,f[3]=11,f[2]=5,f[1]=1
#pragma comment(linker,"/STACK:1024000000,1024000000")
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<map>
#include<cmath>
#include<vector>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
#define pi acos(-1.0)
#define eps 1e-10
#define pf printf
#define sf scanf
#define lson rt<<1,l,m
#define rson rt<<1|1,m+1,r
#define e tree[rt]
#define _s second
#define _f first
#define all(x) (x).begin,(x).end
#define mem(i,a) memset(i,a,sizeof i)
#define for0(i,a) for(int (i)=0;(i)<(a);(i)++)
#define for1(i,a) for(int (i)=1;(i)<=(a);(i)++)
#define mi ((l+r)>>1)
#define sqr(x) ((x)*(x))
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
ll n,p[5][5],ans[5][5],a[5]={0,1,5,11,36};
void multi(ll a[][5],ll b[][5])
{
ll tmp[5][5];
mem(tmp,0);
for1(i,4)
for1(j,4)
for1(k,4)
tmp[i][j]=(tmp[i][j]+a[i][k]*b[k][j])%mod;
for1(i,4)
for1(j,4)
a[i][j]=tmp[i][j];
}
void init()
{
mem(ans,0);
for1(i,4)ans[i][i]=1;
mem(p,0);
p[1][1]=p[1][3]=p[2][1]=p[3][2]=p[4][3]=1;
p[1][2]=5,p[1][4]=-1;
}
void quick_pow(ll x)
{
while(x)
{
if(x&1)multi(ans,p);
multi(p,p);
x>>=1;
}
}
int main()
{
while(~sf("%I64d",&n))
{
if(n<=4)//n小于4时直接输出f[n]
{
pf("%I64d\n",a[n]);
continue;
}
init();//矩阵初始化
quick_pow(n-4);
ll sum=(ans[1][1]*a[4]%mod+ans[1][2]*a[3]%mod+ans[1][3]*a[2]%mod+ans[1][4]*a[1]%mod)%mod;
sum=(sum+mod)%mod;//防止最后得到的sum<0
pf("%I64d\n",sum);
}
return 0;
}