【TCO 2013】Litpanels
2015-09-22 15:39
639 查看
2B LitPanels
Description
一个的棋盘,选择两个
的矩形(可以相交),在矩形内任意染黑格子,问最后棋盘状态的方案数。
不妨先把结果分类。对答案的状态用一个
的包围盒包裹住,分别讨论
包围盒的方案数。
考虑我们需要满足什么条件。
1、包围盒的每一条边都必须有至少一个染色点。
2、能用两个
的矩形包裹所有染色点。
将第二个条件转化一下,考虑到矩形的两种摆放方式,变为:有两种区域,至少有一种内部没有染色点。
那么,我们总共就有6个需要考虑的条件。
枚举每一个点,统计出它在那几个条件上。
这样,我们能得到
个不同的满足情况的条件的点数。
考虑用DP统计合法方案。
表示考虑到了
种点,当前满足情况为
的方案数。
转移:
.
------- 以上来自picks。
我的做法:
分别讨论
包围盒的方案数。只需让四个边界都又被选的点,枚举顶点状态,即可直接求出。
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <cmath> #define Rep(i, x, y) for (int i = x; i <= y; i ++) #define Dwn(i, x, y) for (int i = x; i >= y; i --) #define RepE(i, x) for(int i = pos[x]; i; i = g[i].nex) using namespace std; typedef long long LL; const int N = 45, mod = 1000000007; class LitPanels { public: LL sd[N * N], ans; int Sx, Sy; LL sqr(LL x) { return x * x % mod; } LL sqz(LL x) { return x * (x-1) % mod; } LL Find (int x, int y) { // return 0; int lx = min(2 * Sx, x), ly = min(2 * Sy, y); if (x == 1 || y == 1) { if (x + y <= 2) return 1; return sd[lx + ly - 3]; } int sq = lx * ly, sq2 = sq - 2*(lx+ly) + 4; LL k1 = sd[lx - 2], k2 = sd[ly - 2], ret = 0; (ret += ((sqr(k1) * sqr(k2) % mod) * sd[sq2] % mod) * 7) %= mod; // 4 T (ret += (sd[sq2] * sqz(k2) % mod) * sqr(k1) * 2) %= mod; // 2 T (ret += (sd[sq2] * sqr(k2) % mod) * sqz(k1) * 2) %= mod; // 2 T (ret += (sd[sq2] * sqz(k2) % mod) * sqz(k1) * 4) %= mod; // (ret += (sqr(k1 - 1) * sqr(k2 - 1) % mod) * sd[sq2]) %= mod; return ret; } LL Calc(int x, int y, int lx, int ly) { int sq = (x - 2) * ly + (y - 2) * lx - lx * ly; LL k1 = sd[lx] - 1, k2 = sd[ly] - 1; return (sqr(k1) * sqr(k2) % mod) * sd[sq] % mod; } int countPatterns(int n, int m, int sx, int sy) { Sx = sx, Sy = sy; sd[0] = 1; for (int i = 1; i <= n * m; i ++) sd[i] = sd[i - 1] * 2 % mod; Rep(i, 1, n) { Rep(j, 1, m) { LL ret = 0; if (i <= sx || j <= sy) ret = Find(i, j); else { // continue ; int l1 = max(0, sx * 2 - i), l2 = max(0, sy * 2 - j), sq; sq = 2 * sx * sy - l1 * l2; LL k1 = sd[sx - 1], k2 = sd[sy - 1], sq2 = sq - (sx+sy) * 2 + 2; (ret += (sqr(k1 - 1) * sqr(k2 - 1) % mod) * sd[sq2]) %= mod; // 都不选 ret += sd[sq - 2]; // choose both (ret += (sqz(k1) * sqz(k2) % mod) * sd[sq2] * 2) %= mod; // choose one ret = ret * 2 % mod; ret = (ret - Calc(i, j, l1, l2) + mod) % mod; } (ans += ret * (n - i + 1) * (m - j + 1)) %= mod; } } return int((ans + 1) % mod); } };
相关文章推荐
- PHP编程效率的20个要点
- PHP undefined function curl_init()解决方法
- PHP5.6.6上运行 ecshop 2.7.3常见问题处理
- php设置页面超时时间解决方法
- yii rules使用获取error信息
- PHP Framework - ThinkPHP
- PHP Framework - DooPHP
- 关于php的思考
- phpwind 会员添加字段操作过程
- PHP Framework - Laravel
- PHP Framework - CodeIgniter
- 利用ContentProvider读写短消息。
- PHP Framework - Yii
- 使用phpstorm来进行svn提交
- 利用PHP fsockopen 模拟POST/GET传送数据的方法
- 利用ContentProvider机制读写联系人信息。
- PHP判断字符串长度的两种方法很实用
- PHP+Mysql+Sphinx高效的站内搜索引擎搭建详释
- PHP的一个加密算法
- ContentProvider的详细用法