题意
给出n行m列的迷宫0可走1不可走,有两个操作,操作1变换点(a,b)的值,操作2查询(1,a)到(n,b)的方案数
题解
设(F[i][j])为第i-1行到达第i行第j列的方案数,若点((i,j))上下为0的可延伸范围为((l,r)),则(F[i][j] = sum_{k=l}^r F[i-1][k])
由这个式子就可以构造出第i-1行到第i行方案数的转移矩阵,用线段树维护一下区间矩阵乘积
代码
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <bitset>
using namespace std;
typedef long long ll;
const int mx = 5e4+5;
const int mod = 1e9+7;
char mp[mx][12];
int n, m, q;
struct Matrix {
ll a[12][12];
Matrix() {memset(a, 0, sizeof(a));}
Matrix(int op) {
memset(a, 0, sizeof(a));
for (int i = 1; i <= m; i++) a[i][i] = 1;
}
Matrix operator * (Matrix other) const{
Matrix tmp = Matrix();
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= m; j++) {
for (int k = 1; k <= m; k++) {
tmp.a[i][j] += a[i][k] * other.a[k][j] % mod;
tmp.a[i][j] %= mod;
}
}
}
return tmp;
}
}mat[mx<<2];
void pushUp(int rt) {
mat[rt] = mat[rt<<1] * mat[rt<<1|1];
}
void InitData(int pos, int rt) {
mat[rt] = Matrix();
for (int i = 1; i <= m; i++) {
for (int j = i; j <= m && mp[pos][j] == '0'; j++) {
mat[rt].a[j][i] = 1;
}
for (int j = i; j >= 1 && mp[pos][j] == '0'; j--) {
mat[rt].a[j][i] = 1;
}
}
}
void build(int l, int r, int rt) {
if (l == r) {
if (r == 1) mat[rt] = Matrix(0);
else InitData(r, rt);
return;
}
int mid = (l + r) / 2;
build(l, mid, rt<<1);
build(mid+1, r, rt<<1|1);
pushUp(rt);
}
void update(int pos, int l, int r, int rt) {
if (pos == 1) return;
if (l == pos && r == pos) {
InitData(pos, rt);
return;
}
int mid = (l + r) / 2;
if (pos <= mid) update(pos, l, mid, rt<<1);
else update(pos, mid+1, r, rt<<1|1);
pushUp(rt);
}
int main() {
scanf("%d%d%d", &n, &m, &q);
for (int i = 1; i <= n; i++) scanf("%s", mp[i]+1);
build(1, n, 1);
while (q--) {
int op, a, b;
scanf("%d%d%d", &op, &a, &b);
if (op == 1) {
mp[a][b] = (mp[a][b] == '1' ? '0' : '1');
update(a, 1, n, 1);
} else {
Matrix ans = mat[1];
int s[12] = {0};
for (int i = a; i <= m && mp[1][i] == '0'; i++) s[i] = 1;
for (int i = a; i >= 1 && mp[1][i] == '0'; i--) s[i] = 1;
ll res = 0;
for (int i = 1; i <= m; i++) {
res += s[i] * ans.a[i][b];
res %= mod;
}
printf("%lld
", res);
}
}
return 0;
}