矩阵乘法来进行所有路径的运算, 线段树来查询修改。 关键还是矩阵乘法的结合律。
Harry And Math Teacher
Time Limit: 5000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 326 Accepted Submission(s): 89
Problem Description
As we all know, Harry Porter learns magic at Hogwarts School. However, learning magical knowledge alone is insufficient to become a great magician. Sometimes, Harry also has to gain knowledge from other certain subjects, such as language, mathematics, English, and even algorithm.
In Hogwarts, there is a tall castle in which all teachers live. The castle is rather special. In every floor there are two doors, behind each of them there existing two stairs to the next floor’s two doors. And if you are at the i-th floor’s j-th door , then you can just go to the next floor from this door. However, something even more interesting (or we can say "magic") can happen to the stairs: sometimes they break into pieces (making it impossible to go to the next floor), and sometimes the fragments can joint together and become the whole stair again. Now suppose Harry is in the a-th floor (you know, Harry is the hero, so he lives in the teachers’ building somehow), and his math teacher b-th floor. Sometimes the math teacher will call Harry to his room. Facing these magic stairs, Harry gets puzzled how he can go to see the math teacher. Can you help Harry figure out how many ways exactly he can choose without going backwards? You can assume that the change of the stairs will not happen when Harry is on his way. Harry can begin at any doors in floor a and he can end at any doors in floor b. And as Harry want to arrive as soon as possible, so he can not go back to the past. And at the beginning all the stairs are intact. And the answer may be too large, you should output the answer mod 1000000007.
Input
They are sever test cases, you should process to the end of file.
For each test case, there are two integers n and m(2≤n≤50000,1≤m≤50000) in the first line, indicate the number of the castle’s layers and the number of queries. And the following m lines, each line contains three or four integers. If the first integer op equals 0, there are two integers a and b (1≤a<b≤n) follow, indicate the position of Harry and math teacher. Otherwise, there are three integers x,y,z(1≤x<n,1≤y,z≤2)follow, it means that the stair between the xthfloor’s yth door and the (x+1)th floor’s z-th door changes its state(if it is intact, then it breaks else it joints).
Output
For each query, if op equals 0, you should output one line that contains an integer indicates the number of ways from ath floor to the bth floor.
Sample Input
3 1
0 1 3
3 2
1 2 1 1
0 1 3
Sample Output
8
6
Source
#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; #define MOD 1000000007 #define N 50050 struct node { __int64 g[2][2]; }; int n,m; int l[4*N],r[4*N]; node num[4*N]; void up(int s) { num[s].g[0][0]=0;num[s].g[0][1]=0; num[s].g[1][0]=0;num[s].g[1][1]=0; for(int i=0;i<2;i++) for(int j=0;j<2;j++) for(int k=0;k<2;k++) num[s].g[i][j] = (num[s].g[i][j]+num[2*s].g[i][k]*num[2*s+1].g[k][j])%MOD; } node mul(node x,node y) { node s; s.g[0][0]=0; s.g[0][1]=0; s.g[1][0]=0; s.g[1][1]=0; for(int i=0;i<2;i++) for(int j=0;j<2;j++) for(int k=0;k<2;k++) s.g[i][j]=( s.g[i][j]+x.g[i][k]*y.g[k][j])%MOD; return s; } void build(int tl,int tr,int s) { l[s]=tl; r[s]=tr; if(tl==tr) { num[s].g[0][0]=1; num[s].g[0][1]=1; num[s].g[1][0]=1; num[s].g[1][1]=1; return ; } int mid = (tl+tr)/2; build(tl,mid,2*s); build(mid+1,tr,2*s+1); up(s); } void update(int x,int y,int z,int s) { if(l[s]==x&&r[s]==x) { int tx,ty; if(y==1&&z==1) tx=0,ty=0; if(y==1&&z==2) tx=0,ty=1; if(y==2&&z==1) tx=1,ty=0; if(y==2&&z==2) tx=1,ty=1; if(num[s].g[tx][ty]==0) { num[s].g[tx][ty]=1; } else num[s].g[tx][ty]=0; return ; } int mid= (l[s]+r[s])/2; if(x<=mid) update(x,y,z,2*s); else update(x,y,z,2*s+1); up(s); } node ask(int a,int b,int s) { if(l[s]==a&&r[s]==b) { return num[s];//这里查询的不对 } int mid=(l[s]+r[s])/2; if(b<=mid) return ask(a,b,2*s); else if(a>mid) return ask(a,b,2*s+1); else { return mul(ask(a,mid,2*s),ask(mid+1,b,2*s+1)); } } int main() { while(scanf("%d%d",&n,&m)!=EOF) { build(1,n-1,1); for(int i=0;i<m;i++) { int a,b,c,d; scanf("%d%d%d",&a,&b,&c); if(a==0) { node tmp=ask(b,c-1,1); printf("%I64d\n", (tmp.g[0][0]+tmp.g[0][1]+tmp.g[1][0]+tmp.g[1][1])%MOD ); } else { scanf("%d",&d); update(b,c,d,1); } } } return 0; }