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  

解题代码:

View Code
#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;
}

        

原文地址:https://www.cnblogs.com/yefeng1627/p/2813776.html