问题描述
小明最近迷上了积木画, 有这么两种类型的积木, 分别为 I 型(大小为 2 个单位面积) 和 L 型 (大小为 3 个单位面积):
同时, 小明有一块面积大小为 2×N 的画布, 画布由 2×N 个1×1 区域构成。小明需要用以上两种积木将画布拼满, 他想知道总共有多少种不同的方式? 积木可以任意旋转, 且画布的方向固定。
输入格式:
输入一个整数 N,表示画布大小。
输出格式:
输出一个整数表示答案。由于答案可能很大,所以输出其对 1000000007 取模后的值。
思路
代码(Python)
import os
import sys
# 请在此输入您的代码、
mod = 10 ** 9 + 7
def multi(B, C):
res = [[0] * 3 for _ in range(3)]
for i in range(3):
for j in range(3):
for k in range(3):
res[i][j] = (res[i][j] + B[i][k] * C[k][j] % mod) % mod
return res
def fast_power(A, m):
res = [[1, 0, 0],
[0, 1, 0],
[0, 0, 1]]
while m > 0:
if m % 2:
res = multi(res, A)
A = multi(A, A)
m >>= 1
return res
def main():
n = int(input())
f = [0, 1, 2, 5]
if n <= 3:
print(f[n])
return
mat = [[2, 1, 0],
[0, 0, 1],
[1, 0, 0]]
t = fast_power(mat, n - 3)
ans = (t[0][0] * 5 + t[1][0] * 2 + t[2][0] * 1) % mod
print(ans % mod)
main()
代码(Java)
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改
public class Main {
private final static int MOD = (int)(1e9 + 7);
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
//在此输入您的代码...
int n = scan.nextInt();
int f[] = {0, 1, 2, 5};
if (n < 4) {
System.out.println(f[n]);
return;
}
long[][] mat = {{2, 1, 0}, {0, 0, 1}, {1, 0, 0}};
long[][] t = fastPower(mat, n - 3);
long ans = (t[0][0] * 5 + t[1][0] * 2 + t[2][0]) % MOD;
System.out.println(ans);
scan.close();
}
private static long[][] fastPower(long[][] A, int b) {
long[][] res = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
while(b > 0) {
if ((b & 1) == 1) {
res = multiply(res, A);
}
A = multiply(A, A);
b >>= 1;
}
return res;
}
private static long[][] multiply(long[][] A, long[][] B) {
long[][] res = new long[3][3];
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
for (int k = 0; k < 3; ++k) {
res[i][j] = (A[i][k] * B[k][j] % MOD + res[i][j]) % MOD;
}
}
}
return res;
}
}