百度之星 12-12 题目二

阅读http://blog.csdn.net/niuxianzhuo/article/details/8285854后,深有感触。

代码如下:

#include <cstdlib>
#include <cstdio>
#include <cstring>
using namespace std;

const int MOD = 2012;

/*
    给定一个边长为偶数个(N)方格组成的正方形
    现在由内到外每一个四边形为一层,每个方格
    由0,1组成,现在要求是不同层之间不能够有
    两个1相邻,现在给定N,问多少种情况
    这里有一个很巧妙的转化,即是将我们关心的
    相同层的关系转化为不同层的关系,这个转化
    就使的问题变得独立和模块化,详见大牛博客 
    http://blog.csdn.net/niuxianzhuo/article/details/8285854
*/

int f[505], ret[505], N;

/* f用来保存斐波那契数,一波斐波那契数的含义就是
   f[i]表示一个长度为i的格子放置不相邻的1,有多少种放置方式 
   那么对于f[i] i >= 3 就有类似hdu2046的性质,即对于i+1个方格
   我们直接放置0是可以的,因此f[i] = f[i-1] + x, x为其余部分
   那么如果要放置1的话,那么要求i个位置必须放置0,那么方案数
   就是f[i-2]既然i+1号位置1,0两种情况都已经考虑,因此f[i] = f[i-1] +f[i-2]
   就是最后的结果,其满足斐波那契数列的性质,有f[1] = 2, f[2] = 3 
*/ 
// 输入数据N的范围为2-500之间的偶数

void solve() {
    f[1] = 2, f[2] = 3;
    for (int i = 3; i <= 500; ++i) {
        f[i] = f[i-1] + f[i-2];
        f[i] %= MOD;
    } // 求出前500个递推数
    for (int i = 2; i <= 500; i+=2) {
        ret[i] = 1;
        // 最长的L长度为i-1 
        for (int j = i-1; j >= 1; j -= 2) {
            ret[i] *= f[j];
            ret[i] %= MOD;
        }
        ret[i] *= ret[i];
        ret[i] %= MOD;
        ret[i] *= ret[i];
        ret[i] %= MOD;
    } // 求解最后的答案
}

int main() {
    solve(); // 先进行一次预处理
    while (scanf("%d", &N) == 1) {
        printf("%d\n", ret[N]);
    }
    return 0;    
}

 

posted @ 2012-12-13 15:12  沐阳  阅读(496)  评论(0编辑  收藏  举报