您的位置:首页 > 其它

BZOJ4000 [TJOI2015]棋盘

2015-05-12 23:12 162 查看
首先是状态压缩DP。。。

然后我们发现转移都是一样的。。。可以矩阵优化。。。

于是做完啦QAQQQ

题目读不懂?恩多读几遍就读懂了,诶诶诶!别打我呀!

/**************************************************************
Problem: 4000
User: rausen
Language: C++
Result: Accepted
Time:208 ms
Memory:920 kb
****************************************************************/

#include <cstdio>
#include <cstring>
#include <vector>

using namespace std;
typedef unsigned int uint;
const int N = 75;

inline int read();

int n, m, p, K, Mx;
int a

, f
;
vector <int> mp[3];
uint ans;

struct mat {
uint x[64][64];
mat() {
memset(x, 0, sizeof(x));
}
inline void one() {
static int i;
*this = mat();
for (i = 0; i < Mx; ++i) x[i][i] = 1;
}
inline uint* operator [] (int t) {
return x[t];
}

inline mat operator * (const mat &m) const {
static mat res;
static int i, j, k;
res = mat();
for (i = 0; i < Mx; ++i)
for (j = 0; j < Mx; ++j)
for (k = 0; k < Mx; ++k)
res[i][j] += x[i][k] * m.x[k][j];
return res;
}
} A;

inline mat pow(const mat& m, int y) {
static mat x, res;
x = m, res.one();
int i, j;
while (y) {
if (y & 1) res = res * x;
x = x * x, y >>= 1;
}
return res;
}

inline bool in(int x) {
return 0 <= x && x < m;
}

inline bool check(int s1, int s2) {
static int i, j, t;
for (i = 0; i < m; ++i) if ((s1 >> i) & 1) {
for (j = 0; j < mp[1].size(); ++j)
if (in(t = i + mp[1][j]) && ((s1 >> t) & 1)) return 0;
for (j = 0; j < mp[2].size(); ++j)
if (in(t = i + mp[2][j]) && ((s2 >> t) & 1)) return 0;
}
for (i = 0; i < m; ++i) if ((s2 >> i) & 1) {
for (j = 0; j < mp[1].size(); ++j)
if (in(t = i + mp[1][j]) && ((s2 >> t) & 1)) return 0;
for (j = 0; j < mp[0].size(); ++j)
if (in(t = i + mp[0][j]) && ((s1 >> t) & 1)) return 0;
}
return 1;
}

int main() {
int i, j;
n = read(), m = read(), p = read(), K = read(), Mx = 1 << m;
for (i = 0; i < 3; ++i)
for (j = 0; j < p; ++j)
if (read() && !(i == 1 && j == K)) mp[i].push_back(j - K);
for (i = 0; i < Mx; ++i)
for (j = 0; j < Mx; ++j) A[i][j] = check(i, j);
for (i = 0; i < Mx; ++i) f[i] = bool(A[0][i]);
A = pow(A, n);
for (i = 0; i < Mx; ++i) ans += f[i] * A[i][0];
printf("%u\n", ans);
return 0;
}

inline int read() {
static int x;
static char ch;
x = 0, ch = getchar();
while (ch < '0' || '9' < ch)
ch = getchar();
while ('0' <= ch && ch <= '9') {
x = x * 10 + ch - '0';
ch = getchar();
}
return x;
}


View Code
(p.s. 这道题是0开始标号的。。。注意了QAQQQ)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: