P3977 [TJOI2015] 棋盘 题解
SpringFullGarden · · 题解
题意
题目中的所有编号都是从
有一个
思路
发现
先预处理出所有合法的状态
但是这样时间复杂度是
观察到
设
第一行可以预处理出来,状态
最后答案为
代码
struct node {
ll a[80][80];
} zero, one, f, g;
ll N, a[20];
const ll mod = (1ll << 32);
vector <ll> v;
node mul(node x, node y) {
node res = zero;
for(ll i = 0; i <= N; i++)
for(ll j = 0; j <= N; j++)
for(ll k = 0; k <= N; k++)
res.a[i][j] = (res.a[i][j] + x.a[i][k] * y.a[k][j] % mod) % mod;
return res;
}
node pw(node x, ll y) {
node res = one;
while(y) {
if(y & 1) res = mul(res, x);
x = mul(x, x), y >>= 1;
}
return res;
}
signed main() {
ll n = rd(), m = rd(), p = rd(), k = rd();
N = (1 << m) - 1;
for(ll i = 1; i <= 3; i++)
for(ll j = 0; j < p; j++) a[i] |= rd() * (1ll << j);
for(ll s = 0; s <= N; s++) {
one.a[s][s] = 1;
ll flag = 1;
for(ll i = 0; i < m; i++) {
if(!((1 << i) & s)) continue;
ll t = s;
if(i < k) t <<= k - i;
if(i > k) t >>= i - k;
if((t & a[2]) != (1 << k)) flag = 0, i = m;
}
if(flag) v.push_back(s), g.a[1][s] = 1;
}
for(ll s : v) for(ll t : v) {
ll flag = 1;
for(ll i = 0; i < m; i++) {
if(!((1 << i) & t)) continue;
ll tt = s;
if(i < k) tt <<= k - i;
if(i > k) tt >>= i - k;
if(tt & a[1]) flag = 0, i = m;
}
for(ll i = 0; i < m; i++) {
if(!((1 << i) & s)) continue;
ll tt = t;
if(i < k) tt <<= k - i;
if(i > k) tt >>= i - k;
if(tt & a[3]) flag = 0, i = m;
}
if(flag) f.a[t][s] = 1;
}
node res = mul(g, pw(f, n - 1));
ll ans = 0;
for(ll i = 0; i <= N; i++) ans = (ans + res.a[1][i]) % mod;
cout << (ans + mod) % mod;
return 0;
}