您的位置:首页 > 编程语言 > PHP开发

【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);
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: