BaiduStar 2.du熊填数字 二维转一维后递推
du熊填数字
Time Limit: 3000/2000 MS (C/Others) Memory Limit: 65536/32768 K (C/Others)
本次组委会推荐使用C、C++
Problem Description
du熊这几天使劲的往一个n 行n列的矩阵填0和1这两个数字,n为偶数,而且矩阵由里向外分成了n / 2层。比如n = 6时,矩阵的分层如下:
du熊填数时有一个要求:不能存在两个相邻的1,且位于不同的层(这里的相邻指两格子共用一条线)。
请你帮du熊计算一下有多少种填法。
Input
输入包含多组测试数据,每组数据包含一个偶数n (2 <= n <= 500)。
Output
请计算并输出对2012取余后的结果。
Sample Input
2
4
Sample Output
16
1952
Hint
当n = 4时
1011
0100
0100
0000
是满足要求的
1111
0100
0100
0000
是不满足要求的,因为第一行第二列的1和第二行第二列的1相邻且位于不同的层。
2-500 结果表格
16,1952,564,316,368,112,1188,1404,1592,620,1876,528,1268,1552,648,1708,1048,600
,1416,1128,1800,1204,1164,620,388,700,340,1896,88,1640,644,820,760,1764,28,536
,1600,1356,584,1716,1408,1160,1060,384,432,1588,1400,276,1532,1416,1196,324
,1400,584,1264,1944,188,528,276,1360,1708,944,128,1792,924,1872,216,1492,176
,996,1024,396,1416,312,72,1408,1008,268,996,1896,1268,1468,1264,1248,704,1132
,900,876,88,788,276,1876,1480,512,48,28,1048,312,1584,1328,876,384,996,1772,112
,1168,1172,56,820,268,468,1504,128,584,400,576,1160,104,740,620,484,1944,336
,1992,804,676,1852,1264,288,108,308,876,1480,1248,268,156,1592,692,1536,400
,1652,1052,64,1084,1532,224,1352,1872,104,8,88,292,732,92,892,1404,1160,632
,680,1188,1584,104,1684,244,1204,576,1944,1164,916,1296,1352,400,1288,1608
,1936,292,1292,352,1708,1352,792,1032,1316,384,1588,976,1592,932,1024,1144
,680,264,1512,1264,1944,156,364,1548,776,1292,112,680,364,924,1664,1872,1240
,1480,1608,236,156,1456,1576,200,92,736,1200,1652,4,1832,1584,1296,552,728,380
,108,1468,704,1848,252,1292,1520,732,1024,1780,1604,916,264,632,108,128,512,788
,1532,1516,1740,504,896,664,564
解题思路:
首先观察题目图 :
依据题意,仅有不同层间出现相邻1才有冲突,同层间无影响,且为正方形对称, 那么,我们可以把图形分解成四个部分分别考虑, 之间无影响.且各个部分方案数完全相同.
我们考虑以 n = 6 时, 左上角部分情形来分析, 如图 图中相冲突的为相同颜色, 不同颜色间无冲突, 通过这样,我们就把问题分解转换
成在线形格子上的放置 0/1 问题. 则总共有 n/2 条线形格子排列.
定义一个函数 F(n) 表示长度为n的格子, 不存在连续的两个1的排列方案数.
假定 [1,n-1] 区间 F[i] 已求得. 当添加一个格子进来时, 要满足要求则存在 第n位为0 和 第n位为1 两种情况:
当第n位为0时,则方案数为 n-1个格子的合法方案数目,即为F[n-1]
当第n位为1时,则第n-1位必定为0,则递归得到 方案数为 F[n-2]
所有得出 F(n) = F(n-1)+F(n-2) , 初始条件为: F(0) = 1, F(1) = 2
在本题中, N层的格子则有 N/2 条 L形格子, 所以对于每一层有 G(N) = F(N-1)
所有左上角的填充方案数 cnt = G(N)*G(N-2)*...*G(2) 共 N/2个
又划分的四部分完全独立, 则最终结果为 answer = cnt^4
对于递推公式,我们也可以通过数学公式得到:
定义函数F(n)为 n-1个直线格子,不出现连续两个1的方案总数.
因为任意两个1之间都会存在0,转换下角度就是 往一组0序列的间隔中插入一些1. 则m个0的排列存在m+1个序列则
F(n) = C(0,n) + C(1,n-1) + C(2,n-2) + .. + C(n/2,n-n/2) ps: n-1个格子,最多只能放n/2个1
另: F(n-1) = C(0,n-1) + C(1,n-2)+ C(2,n-3) + ... + C( (n-1)/2, (n-1)-(n-1)/2 )
F(n-2) = C(0,n-2) + C(1,n-3) + C(3, n -4) + ... + C( (n-2)/2, (n-2)-(n-2)/2 )
有组合公式 C(m,n) = C(m,n-1) + C(m-1,n-1 ) 化简可得 F(n) = F(n-1) + F(n-2), F(1) = 1 , F(2) = 2
解题代码:
#include<stdio.h> #include<stdlib.h> #include<string.h> const int mod = 2012; const int N = 510; int F[N] = {0,1,2}; int n, ans[N]; void init() { for(int i = 3; i <= 500; i++) F[i] = (F[i-1]+F[i-2])%mod; for(n = 2; n <= 500; n += 2) { int sum = 1; for(int i = 1; i <= n/2; i++) sum = (sum*F[2*i])%mod; ans[n] = ((sum*sum)%mod) * ((sum*sum)%mod) % mod; } } int main() { init(); while( scanf("%d", &n) != EOF) { printf("%d\n", ans[n] ); } return 0; }