链接:
http://exam.upc.edu.cn/problem.php?id=4333
题目:
题目描述
Bob’s school has a big playground, boys and girls always play games here after school.
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?
输入
There are no more than 5000 test cases.
Each test case only contains one positive integer n(1 ≤ n ≤ 1018) in a line.
输出
For each test cases, output the answer mod 1000000007 in a line.
样例输入
1
2
样例输出
1
5
题意:
用没有数量限制 2×1 和 1×2 的矩形去铺一块 4×n 的矩形,有多少种方法。
思路:
先写了个DFS暴力打出
n
在区间
bool book[7][1007];
bool findpos(int &x, int &y) {
for(int i=1 ; i<=4 ; i++) {
for(int j=1 ; j<=n ; j++) {
if(!book[i][j]) {
x = i, y = j;
return false;
}
}
}
return true;
}
void dfs(int x, int y) {
if(!book[x+1][y] && x<4) {
book[x][y] = book[x+1][y] = true;
int newx, newy;
if(findpos(newx, newy)) {
book[x][y] = book[x+1][y] = false;
cnt++;
return ;
}
dfs(newx, newy);
book[x][y] = book[x+1][y] = false;
}
if(!book[x][y+1] && y<n) {
book[x][y] = book[x][y+1] = true;
int newx, newy;
if(findpos(newx, newy)) {
book[x][y] = book[x][y+1] = false;
cnt++;
return ;
}
dfs(newx, newy);
book[x][y] = book[x][y+1] = false;
}
}
得到1 5 11 36 95 281 781 2245 6336 18061
这前十个答案。
然后觉得有一个边长是常数
4
,就写了五层for循环确定ans[i]与前四项和一个常数之间的系数关系,得到:
需要注意的一点是,因为有一个系数是 −1 ,所以在矩阵乘法的过程中,在两两相加的时候要再加上一个mod之后再取模,不然的话有可能出现一个小的正数加上一个大的负数的情况。
实现:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 4;
ll Matrixsize = 4, mod = int(1e9)+7, n;
struct Matrix {
ll m[maxn][maxn];
Matrix(ll i = 0) {
memset(m, 0, sizeof m);
if (i == 1)
for (ll I = 0; I < Matrixsize; I++) m[I][I] = 1;
}
Matrix operator * (const Matrix tmp) const {
Matrix ret;
long long x;
for(ll i=0 ; i<Matrixsize ; i++)
for(ll j=0 ; j<Matrixsize ; j++) {
x=0;
for(ll k=0 ; k<Matrixsize ; k++)
x+=(m[i][k] * tmp.m[k][j] + mod) % mod;
ret.m[i][j] = int(x % mod);
}
return ret;
}
Matrix qpow(long long n) {
Matrix ret = 1, tmp = *this;
while (n > 0) {
if (bool(n & 1)) ret = ret * tmp;
tmp = tmp * tmp;
n >>= 1;
}
return ret;
}
};
int main() {
#ifndef ONLINE_JUDGE
freopen("../in.txt", "r", stdin);
printf("init! init! init!\n");
#endif
Matrix base1 = 0, base2 = 0;
base1.m[0][0] = base1.m[0][2] = base1.m[1][0] = base1.m[2][1] = base1.m[3][2] = 1;
base1.m[0][3] = -1, base1.m[0][1] = 5, base2.m[0][0] = 1;
base2.m[1][0] = 0, base2.m[2][0] = 1, base2.m[3][0] = 1;
while(~scanf("%lld",&n)) printf("%lld\n",(base1.qpow(n)*base2).m[0][0]);
return 0;
}