Knights

来源:互联网 发布:浙江师范行知学院 编辑:程序博客网 时间:2024/05/20 09:26

这里写图片描述

矩阵加快速幂
假设我们考虑 m 为 4 的情况。由于马只能走日,所以能进攻的只有隔壁两列以内的,也就是说我要放置第i列的情况,只需要考虑第i-1和第i-2列的情况。那么就能转换成一个4*3的棋盘,第[1,2]列转换成第[2,3]列。每个状态最多是8个格子,也就是说状态数是28。利用dfs先预处理出哪些方案是合法的,同时生成转移矩阵,如果状态i能从状态j转移过来,那么a[i][j]=1,于是就能通过快速幂来求了。

当时赶时间代码有点丑:p

#include <bits/stdc++.h>using namespace std;#define ll long longconst int d[8][2] = {{1,2},{1,-2},{-1,2},{-1,-2},{2,1},{2,-1},{-2,1},{-2,-1}};const ll mo = 1e9+9;int a[5][5], n, m;struct Matrix {    int a[258][258];    Matrix() {memset(a, 0, sizeof(a));}};Matrix f[5], g[5];Matrix cheng1(Matrix& x, Matrix& y) {    Matrix temp;    for (int i = 0; i < 32; i++)        for (int j = 0; j < 32; j++)            for (int k = 0; k < 32; k++) {                temp.a[i][j] = ((ll)temp.a[i][j]+(1LL*x.a[i][k]*y.a[k][j])%mo)%mo;            }    return temp;}Matrix cheng2(Matrix& x, Matrix& y) {    Matrix temp;    for (int i = 0; i < 64; i++)        for (int j = 0; j < 64; j++)            for (int k = 0; k < 64; k++) {                temp.a[i][j] = ((ll)temp.a[i][j]+(1LL*x.a[i][k]*y.a[k][j])%mo)%mo;            }    return temp;}Matrix cheng3(Matrix& x, Matrix& y) {    Matrix temp;    for (int i = 0; i < 128; i++)        for (int j = 0; j < 128; j++)            for (int k = 0; k < 128; k++) {                temp.a[i][j] = ((ll)temp.a[i][j]+(1LL*x.a[i][k]*y.a[k][j])%mo)%mo;            }    return temp;}Matrix cheng4(Matrix& x, Matrix& y) {    Matrix temp;    for (int i = 0; i < 256; i++)        for (int j = 0; j < 256; j++)            for (int k = 0; k < 256; k++) {                temp.a[i][j] = ((ll)temp.a[i][j]+(1LL*x.a[i][k]*y.a[k][j])%mo)%mo;            }    return temp;}bool check(int n, int m) {    for (int i = 1; i <= n; i++)        for (int j = 1; j <= m; j++) if (a[i][j]) {            for (int k = 0; k < 8; k++) {                int x = i+d[k][0], y = j+d[k][1];                if (!(x >= 1 && x <= n && y >= 1 && y <= m)) continue;                if (a[x][y]) return false;            }        }    return true;}int calc(int n, int m) {    int x = 0, y = 1;    for (int i = 1; i <= n; i++)        for (int j = m; j <= m+1; j++) {            x += a[i][j]*y;            y *= 2;        }    return x;}void dfs(int x, int y, int n) {    if (x > n) {        if (check(n, 3)) {            f[n].a[calc(n, 1)][calc(n, 2)] = 1;        }        if (check(n, 2)) g[n].a[1][calc(n, 1)] = 1;        return;    }    a[x][y] = 1;    dfs(y==3?x+1:x, (y+1)%4, n);    a[x][y] = 0;    dfs(y==3?x+1:x, (y+1)%4, n);}Matrix ans, t;int main() {    //freopen("input.txt","r",stdin);    memset(f, 0, sizeof(f));    memset(a, 0, sizeof(a));    for (int i = 1; i <= 4; i++) dfs(1,1,i);    int T;    scanf("%d", &T);    while (T--) {        scanf("%d %d", &n, &m);        if (n == 1 && m == 1) {            printf("2\n"); continue;        }        if (n > m) swap(n, m);        ans = g[n];        t = f[n];        m -= 2;        while (m) {            if (m%2) {                if (n == 1) ans = cheng1(ans,t);                if (n == 2) ans = cheng2(ans,t);                if (n == 3) ans = cheng3(ans,t);                if (n == 4) ans = cheng4(ans,t);            }            if (n == 1) t = cheng1(t,t);            if (n == 2) t = cheng2(t,t);            if (n == 3) t = cheng3(t,t);            if (n == 4) t = cheng4(t,t);            //t = t*t;            m /= 2;        }        ll tot = 0;        for (int i = 0; i < 256; i++) {            tot += ans.a[1][i];            tot %= mo;        }        printf("%lld\n", tot);    }}
原创粉丝点击