百度之星 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; }