首页 > 代码库 > HDU5068(Harry And Math Teacher)

HDU5068(Harry And Math Teacher)

题目地址:Harry And Math Teacher

 

题目大意:

    有N层楼,每层楼都有两个门,i 层楼的两扇门到i+1层楼的两扇门各有通道互不影响(例如:i层楼门号有1、2,i+1层楼门号有1、2则有四条通道 1->1、1->2、2-> 1 、2-> 2),其中可以修改通道的状态,如果op值为‘1’的时候 将x楼与x+1层楼之间的y-z门的这条通道的状态改变,如果先前是通路则切断无法通过,如果先前是断路的状态,则恢复通路可以通过。如果op为‘0’,在表示询问a->b 有多少种路径可以到达。

 

解题思路:

    线段数,节点存储通道路径的矩阵,矩阵的相乘结果刚好是下一层楼四条边的路径种类和,之前用的方法是想,计算左边门和右边门的所有情况和,然后加和,但是难判断的是上一层的右边得到的路径种类和以及左边得到的路径种类和,汇流到了下一层的左边边门和右边门时,很难分配该层的到下一层的左右门各有多少条路径,反正说不太清,代码编的就很乱,不想在改了。  正好利用矩阵完美解决了路径汇总到下一层左右门时路径种类个数的问题,最后计算出矩阵,然后将矩阵里所有的值相加就是答案。

 

代码:

  1 #include <algorithm>  2 #include <iostream>  3 #include <sstream>  4 #include <cstdlib>  5 #include <cstring>  6 #include <cstdio>  7 #include <string>  8 #include <bitset>  9 #include <vector> 10 #include <queue> 11 #include <stack> 12 #include <cmath> 13 #include <list> 14 //#include <map> 15 #include <set> 16 using namespace std; 17 /***************************************/ 18 #define ll long long 19 #define int64 __int64 20 #define PI 3.1415927 21 /***************************************/ 22 const int INF = 0x7f7f7f7f; 23 const double eps = 1e-8; 24 const double PIE=acos(-1.0); 25 const int d1x[]= {0,-1,0,1}; 26 const int d1y[]= {-1,0,1,0}; 27 const int d2x[]= {0,-1,0,1}; 28 const int d2y[]= {1,0,-1,0}; 29 const int fx[]= {-1,-1,-1,0,0,1,1,1}; 30 const int fy[]= {-1,0,1,-1,1,-1,0,1}; 31 const int dirx[]= {-1,1,-2,2,-2,2,-1,1}; 32 const int diry[]= {-2,-2,-1,-1,1,1,2,2}; 33 /*vector <int>map[N];map[a].push_back(b);int len=map[v].size();*/ 34 /***************************************/ 35 void openfile() 36 { 37     freopen("data.in","rb",stdin); 38     freopen("data.out","wb",stdout); 39 } 40 priority_queue<int> qi1; 41 priority_queue<int, vector<int>, greater<int> >qi2; 42 /**********************华丽丽的分割线,以上为模板部分*****************/ 43 const int M=50010; 44 const int64 MOD=1000000007; 45 struct tree 46 { 47     int64 matrix[3][3]; 48     int left,right; 49 } node[M*4];  //需开四倍的空间大小 50 int64 cnt; 51 tree pp; 52 tree mul(tree a,tree b,int l,int r) 53 { 54     int i,j,k; 55     memset(pp.matrix,0,sizeof(pp.matrix)); 56     pp.left=l; 57     pp.right=r; 58     for(i=1; i<=2; i++) 59         for(j=1; j<=2; j++) 60             for(k=1; k<=2; k++) 61             { 62                 pp.matrix[i][j]+=a.matrix[i][k]%MOD*b.matrix[k][j]%MOD; 63                 pp.matrix[i][j]%=MOD; 64             } 65     return pp; 66 } 67 void build__tree(int id,int l,int r)  //建树 68 { 69     int mid=(l+r)/2; 70     node[id].left=l;   //初始化赋值区间的坐标 71     node[id].right=r; 72     if (l==r) 73     { 74         node[id].matrix[1][1]=1; 75         node[id].matrix[1][2]=1; 76         node[id].matrix[2][1]=1; 77         node[id].matrix[2][2]=1; 78         return ; 79     } 80     build__tree(id*2,l,mid);  //左孩子 81     build__tree(id*2+1,mid+1,r); //右孩子 82     node[id]=mul(node[id*2],node[id*2+1],l,r); 83     return ; 84 } 85 tree tmp; 86 int query(int id,int l,int r)  //查询区间的总和 87 { 88     int mid=(node[id].left+node[id].right)/2; 89     if (node[id].left==l&&node[id].right==r) 90     { 91         tmp=mul(tmp,node[id],l,r); 92     } 93     else if (l>mid)   //[l,r]在右孩子部分 94         query(id*2+1,l,r); 95     else if (r<=mid) // [l,r]在左孩子部分 96         query(id*2,l,r); 97     else  //[l,r]区间,左右孩子都有分别递归。 98     { 99         query(id*2,l,mid);100         query(id*2+1,mid+1,r);101     }102     return 0;103 }104 void updata(int id,int pos,int y,int z)  //从上向下寻找节点,找到节点后然后从下往上更新节点的val值105 {106     if (node[id].left==pos&&node[id].right==pos)//找到该节点107     {108         node[id].matrix[y][z]=1-node[id].matrix[y][z];109         return ;110     }111     int mid=(node[id].left+node[id].right)/2;112     if (pos<=mid)  //节点在左孩子部分113         updata(id*2,pos,y,z);114     else //节点在右孩子部分115         updata(id*2+1,pos,y,z);116     node[id]=mul(node[id*2],node[id*2+1],node[id].left,node[id].right);117 }118 int main()119 {120     int n,m;121     while(scanf("%d%d",&n,&m)!=EOF)122     {123         build__tree(1,1,n-1);124         int op;125         int i;126         for(i=0; i<m; i++)127         {128             scanf("%d",&op);129             if (!op)130             {131                 tmp.matrix[1][1]=1;132                 tmp.matrix[1][2]=0;133                 tmp.matrix[2][1]=0;134                 tmp.matrix[2][2]=1;135                 int a,b;136                 scanf("%d%d",&a,&b);137                 query(1,a,b-1);138                 cnt=0;139                 for(int i=1;i<=2;i++)140                    for(int j=1;j<=2;j++)141                    {142                        cnt+=tmp.matrix[i][j]%MOD;143                        cnt%=MOD;144                    }145                 printf("%I64d\n",cnt);146             }147             else148             {149                 int x,y,z;150                 scanf("%d%d%d",&x,&y,&z);151                 updata(1,x,y,z);152             }153         }154         memset(node,0,sizeof(node));155     }156     return 0;157 }
View Code

错误的代码:

很乱,但是编了好长时间 ,舍不得,回头有时间在看看把。

  1 #include <algorithm>  2 #include <iostream>  3 #include <sstream>  4 #include <cstdlib>  5 #include <cstring>  6 #include <cstdio>  7 #include <string>  8 #include <bitset>  9 #include <vector> 10 #include <queue> 11 #include <stack> 12 #include <cmath> 13 #include <list> 14 //#include <map> 15 #include <set> 16 using namespace std; 17 /***************************************/ 18 #define ll long long 19 #define int64 __int64 20 #define PI 3.1415927 21 /***************************************/ 22 const int INF = 0x7f7f7f7f; 23 const double eps = 1e-8; 24 const double PIE=acos(-1.0); 25 const int d1x[]= {0,-1,0,1}; 26 const int d1y[]= {-1,0,1,0}; 27 const int d2x[]= {0,-1,0,1}; 28 const int d2y[]= {1,0,-1,0}; 29 const int fx[]= {-1,-1,-1,0,0,1,1,1}; 30 const int fy[]= {-1,0,1,-1,1,-1,0,1}; 31 const int dirx[]= {-1,1,-2,2,-2,2,-1,1}; 32 const int diry[]= {-2,-2,-1,-1,1,1,2,2}; 33 /*vector <int>map[N];map[a].push_back(b);int len=map[v].size();*/ 34 /***************************************/ 35 void openfile() 36 { 37     freopen("data.in","rb",stdin); 38     freopen("data.out","wb",stdout); 39 } 40 priority_queue<int> qi1; 41 priority_queue<int, vector<int>, greater<int> >qi2; 42 /**********************华丽丽的分割线,以上为模板部分*****************/ 43 const int M=50010; 44 const long long MOD=1000000007; 45 struct tree 46 { 47     long long sum; 48     long long sum1,sum2; 49     long long  x,y; 50     long long d[5]; 51     int left,right;  //记录区间的左右闭区间坐标 52 } node[M*4];  //需开四倍的空间大小 53 long long cnt1,cnt2; 54 long long aaans; 55 void MM() 56 { 57     long long b=MOD-2; 58     long long ans=1; 59     long long a=2; 60     while(b) 61     { 62         if (b&1) 63             ans=(ans%MOD*a%MOD)%MOD; 64         a=(a%MOD*a%MOD)%MOD; 65         b>>=1; 66     } 67     aaans=ans; 68     return ; 69 } 70 long long aaans1; 71 void MMM() 72 { 73     long long b=MOD-2; 74     long long ans=1; 75     long long a=4; 76     while(b) 77     { 78         if (b&1) 79             ans=(ans%MOD*a%MOD)%MOD; 80         a=(a%MOD*a%MOD)%MOD; 81         b>>=1; 82     } 83     aaans1=ans; 84     return ; 85 } 86 void build__tree(int id,int l,int r)  //建树 87 { 88     int mid=(l+r)/2; 89     node[id].left=l;   //初始化赋值区间的坐标 90     node[id].right=r; 91     for(int i=1; i<=4; i++) 92         node[id].d[i]=1; 93     if (l==r) 94     { 95         node[id].sum1=2;  //初始化区间节点的val值 96         node[id].sum2=2; 97         node[id].x=2; 98         node[id].y=2; 99         node[id].sum=node[id].sum1+node[id].sum2;100         return ;101     }102     build__tree(id*2,l,mid);  //左孩子103     build__tree(id*2+1,mid+1,r); //右孩子104     node[id].x=node[id*2+1].x;105     node[id].y=node[id*2+1].y;106     node[id].sum=(node[id*2].sum%MOD*node[id*2+1].sum%MOD)%MOD*aaans%MOD;107     node[id].sum1=(node[id].sum%MOD*node[id].x%MOD)%MOD*aaans1%MOD;108     node[id].sum2=(node[id].sum%MOD*node[id].y%MOD)%MOD*aaans1%MOD;109 }110 int query(int id,int l,int r)  //查询区间的总和111 {112     int mid=(node[id].left+node[id].right)/2;113     if (node[id].left==l&&node[id].right==r)114     {115         cnt1=(cnt1*node[id].sum1)%MOD;116         cnt2=(cnt2*node[id].sum2)%MOD;117         return 0;118     }119     else if (l>mid)   //[l,r]在右孩子部分120         query(id*2+1,l,r);121     else if (r<=mid) // [l,r]在左孩子部分122         query(id*2,l,r);123     else  //[l,r]区间,左右孩子都有分别递归。124     {125         query(id*2,l,mid);126         query(id*2+1,mid+1,r);127     }128     return 0;129 }130 void updata(int id,int pos,int val)  //从上向下寻找节点,找到节点后然后从下往上更新节点的val值131 {132     if (node[id].left==pos&&node[id].right==pos)//找到该节点133     {134         if (node[id].d[val]==1)135         {136             node[id].d[val]=0;137             if (val%2)138             {139                 node[id].x--;140                 node[id].sum1--;141             }142             else143             {144                 node[id].y--;145                 node[id].sum2--;146             }147         }148         else149         {150             node[id].d[val]=1;151             if (val%2)152             {153                 node[id].x++;154                 node[id].sum1++;155             }156             else157             {158                 node[id].y++;159                 node[id].sum2++;160             }161         }162         node[id].sum=node[id].sum1+node[id].sum2;163         return ;164     }165     int mid=(node[id].left+node[id].right)/2;166     if (pos<=mid)  //节点在左孩子部分167         updata(id*2,pos,val);168     else //节点在右孩子部分169         updata(id*2+1,pos,val);170     node[id].x=node[id*2+1].x;171     node[id].y=node[id*2+1].y;172     int b;173     int ans;174     if (node[id*2].sum*node[id*2+1].sum<4)175     {176         node[id].sum1=node[id*2].sum1%MOD*node[id*2+1].sum1%MOD;177         node[id].sum2=node[id*2].sum2%MOD*node[id*2+1].sum2%MOD;178         node[id].sum=(node[id].sum1+node[id].sum2)%MOD;179     }180     else181     {182         long long a=node[id].x+node[id].y;183         node[id].sum=(node[id*2].sum%MOD*node[id*2+1].sum%MOD)%MOD*aaans%MOD;184         /*ans=1;185         a=node[id].x+node[id].y;186         b=MOD-2;187         while(b)188         {189             if (b&1)190                 ans=(ans%MOD*a%MOD)%MOD;191             a=(a%MOD*a%MOD)%MOD;192             b>>=1;193         } */194         if (a)195         {196             node[id].sum1=(node[id].sum%MOD*node[id].x%MOD)%MOD/a%MOD;197             node[id].sum2=(node[id].sum%MOD*node[id].y%MOD)%MOD/a%MOD;198         }199         else200         {201             node[id].sum1=0;202             node[id].sum2=0;203         }204     }205 }206 int main()207 {208     int n,m;209     MM();210     MMM();211     while(scanf("%d%d",&n,&m)!=EOF)212     {213         build__tree(1,1,n-1);214         int op;215         int i;216         for(i=0; i<m; i++)217         {218             scanf("%d",&op);219             if (!op)220             {221                 int a,b;222                 cnt1=1;223                 cnt2=1;224                 scanf("%d%d",&a,&b);225                 query(1,a,b-1);226                 printf("%I64d\n",(cnt1+cnt2)%MOD);227             }228             else229             {230                 int x,y,z;231                 scanf("%d%d%d",&x,&y,&z);232                 int ce=0;233                 if (y==1&&z==1)234                     ce=1;235                 if (y==1&&z==2)236                     ce=2;237                 if (y==2&&z==1)238                     ce=3;239                 if (y==2&&z==2)240                     ce=4;241                 updata(1,x,ce);242             }243         }244     }245     return 0;246 }247 /*248 50000 100249 0 1 50000250 0 2 50000251 0 10000 10001252 0 10000 10010253 1 10000 1 1254 1 10010 2 1255 1 10000 2 1256 1 10000 1 2257 0 10000 50000258 0 10000 10001259 0 10000 10002260 0 10000 10003261 0 10000 10004262 0 10000 10005263 0 10000 10006264 0 10000 10007265 0 10000 10008266 0 10000 10009267 0 10000 10010268 0 10000 10011269 0 10000 10012270 0 1 2271 0 1 3272 0 1 4273 0 1 5274 0 1 6275 0 2 3276 0 2 4277 0 2 5278 0 3 4279 0 3 5280 0 3 6281 0 4 5282 0 4 6283 0 5 6284 */285 /*286 50000 100287 1 3 1 1288 1 3 2 1289 1 3 1 2290 1 1 1 1291 1 1 2 1292 1 1 1 2293 1 2 1 1294 1 2 2 1295 1 2 1 2296 0 1 50000297 0 2 50000298 0 3 50000299 0 4 50000300 0 10000 10001301 0 10000 50000302 */
View Code

 

HDU5068(Harry And Math Teacher)