面试题9(变形):矩形覆盖

题目链接:http://ac.jobdu.com/problem.php?pid=1390

思路:设用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形的方法数为Fn

1、考虑最后一个小矩形,假设他是竖着的,那么前n-1个小矩形可以任意放,有Fn-1种放法

2、考虑最后两个小矩形,假设他们都是横着放,那么前n-2个小矩形可以任意放,有Fn-2中放法

上面两种情况是否既包含n个小矩形的所有放法,又不存在重复计算呢?

首先考虑是否会重复,显然不会,最后两个小矩形的放法不一样,不可能重复。

再考虑是否包含了所有情况,我们可以换个角度想想,有没有一种放法不对应到上面的两种情况之一,

我们只能考虑最后两个是否没对应上,因为前面的n-2个包含了所有放法,显然不会出现不对应的情况。

递推公式:Fn = Fn-1 + Fn-2

注:考虑递推时,最重要的是,不重不漏!!!

code:

 1 #include <cstdio>

 2 #include <cstring>

 3 using namespace std;

 4 const int M = 2;

 5 const int MOD = 1000000007;

 6 typedef long long LL;

 7 LL ans[M][M];

 8 LL tmp[M][M];

 9 

10 // 矩阵乘法

11 void matrixMul(LL mat1[M][M], LL mat2[M][M])

12 {

13     LL mat3[M][M];

14     for (int i = 0; i < M; ++i)

15     {

16         for (int j = 0; j < M; ++j)

17         {

18             mat3[i][j] = 0;

19             for (int k = 0; k < M; ++k)

20                 mat3[i][j] += mat1[i][k] * mat2[k][j];

21         }

22     }

23     memcpy(mat1, mat3, sizeof(mat3));

24 }

25 

26 // 矩阵快速幂

27 void matrixQuickMod(int n)

28 {

29     tmp[0][0] = 1;

30     tmp[0][1] = 1;

31     tmp[1][0] = 1;

32     tmp[1][1] = 0;

33 

34     // 将ans处理成单位矩阵

35     memset(ans, 0, sizeof(ans));

36     for (int i = 0; i < M; ++i) ans[i][i] = 1;

37 

38     while (n)

39     {

40         if (n & 1) matrixMul(ans, tmp);        // 当n为奇数时,跟新ans

41         n >>= 1;

42         matrixMul(tmp, tmp);    // 当n为偶数时跟新tmp

43     }

44 }

45 

46 int main()

47 {

48     int n;

49     while (scanf("%d", &n) != EOF)

50     {

51         matrixQuickMod(n);

52         printf("%lld\n", ans[0][0]);

53     }

54     return 0;

55 }

 

你可能感兴趣的:(面试题)