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 }

 

posted @ 2018-12-11 20:11  MJT12044  阅读(209)  评论(0编辑  收藏  举报