HDU 5068 Harry And Math Teacher
Harry And Math Teacher
题意:
n层楼,每层有两扇门,初始时,从第i层到第i+1的所有门都可以相互到达。两种操作,询问从a层到b层的方案数,修改x层到x+1层两扇门之间的连通性。
分析:
线段树维护转移矩阵。
考虑如歌计算a->b的方案数,$f[i][0/1]$表示从起点到第i层,当前在第j扇门时的方案数,那么$f[i][j]=f[i-1][0] \times a[0][j]+f[i-1][1] \times a[1][j]$,$a[][]$为i-1层到i层的联通性。
然后发现如果将a看做一个矩阵的话,就是从a到b-1的所有矩阵乘起来。
修改操作只是修改一个矩阵,所以可以线段树维护。
a数组开了longlong就过了?感觉好像不需要开。
代码:
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<iostream> 5 #include<cmath> 6 #include<cctype> 7 #include<set> 8 #include<queue> 9 #include<vector> 10 #include<map> 11 #define Root 1, n, 1 12 #define lson l, mid, rt << 1 13 #define rson mid + 1, r, rt << 1 | 1 14 using namespace std; 15 typedef long long LL; 16 17 inline int read() { 18 int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; 19 for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f; 20 } 21 22 const int N = 50005; 23 const int mod = 1e9 + 7; 24 25 struct Node{ 26 LL a[2][2]; 27 Node() { memset(a, 0, sizeof(a)); } 28 }T[N << 2]; 29 30 Node operator + (const Node &A,const Node &B) { 31 Node C; 32 for (int k = 0; k < 2; ++k) 33 for (int i = 0; i < 2; ++i) 34 for (int j = 0; j < 2; ++j) { 35 C.a[i][j] += (1ll * A.a[i][k] * B.a[k][j]) % mod; 36 if (C.a[i][j] >= mod) C.a[i][j] -= mod; 37 } 38 return C; 39 } 40 void build(int l,int r,int rt) { 41 if (l == r) { 42 T[rt].a[0][0] = T[rt].a[0][1] = T[rt].a[1][0] = T[rt].a[1][1] = 1; 43 return ; 44 } 45 int mid = (l + r) >> 1; 46 build(lson); build(rson); 47 T[rt] = T[rt << 1] + T[rt << 1 | 1]; 48 } 49 void update(int l,int r,int rt,int p,int x,int y) { 50 if (l == r) { 51 T[rt].a[x][y] ^= 1; return ; 52 } 53 int mid = (l + r) >> 1; 54 if (p <= mid) update(lson, p, x, y); 55 else update(rson, p, x, y); 56 T[rt] = T[rt << 1] + T[rt << 1 | 1]; 57 } 58 Node query(int l,int r,int rt,int L,int R) { 59 if (L <= l && r <= R) return T[rt]; 60 int mid = (l + r) >> 1; 61 if (R <= mid) return query(lson, L, R); 62 else if (L > mid) return query(rson, L, R); 63 else return query(lson, L, R) + query(rson, L, R); 64 } 65 void solve(int n,int m) { 66 build(Root); 67 while (m --) { 68 int opt = read(); 69 if (opt == 0) { 70 int a = read(), b = read(); 71 Node ans = query(Root, a, b - 1); 72 LL sum = (ans.a[0][0] + ans.a[0][1] + ans.a[1][0] + ans.a[1][1]) % mod; 73 printf("%I64d\n", sum); 74 } 75 else { 76 int x = read(), y = read(), z = read(); 77 update(Root, x, y - 1, z - 1); 78 } 79 } 80 } 81 int main() { 82 int n, m; 83 while (~scanf("%d%d", &n, &m)) solve(n, m); 84 return 0; 85 }