BZOJ1875 [SDOI2009]HH去散步
矩阵优化DP。
然而本题用到了骚操作,就是没有办法沿原路走回去,所以我们不能按临接矩阵dp,需要按照边建图
两边联通当且仅当a.from==b.to所以转移dp[i][j]=dp[i][k]*dp[k][j]
多少次就是多少次幂,然后加上与终点联通边的就是答案了。
By:大奕哥
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=2005,mod=45989; 4 struct edge{ 5 int from,to; 6 }e[N<<1]; 7 int cnt=-1,n,m,A,B,t; 8 void add(int x,int y) 9 { 10 cnt++;e[cnt].to=y;e[cnt].from=x; 11 cnt++;e[cnt].to=x;e[cnt].from=y; 12 } 13 struct node 14 { 15 int n,m,s[125][125]; 16 node (){ 17 n=m=0;memset(s,0,sizeof(s)); 18 } 19 node operator *(const node B)const{ 20 node c;c.n=n;c.m=B.m; 21 for(int k=0;k<=m;++k) 22 for(int i=0;i<=n;++i) 23 for(int j=0;j<=B.m;++j) 24 c.s[i][j]=(c.s[i][j]+1ll*s[i][k]*B.s[k][j]%mod)%mod; 25 return c; 26 } 27 void print() 28 { 29 for(int i=0;i<=n;++i) 30 {for(int j=0;j<=m;++j) 31 cout<<s[i][j]<<" "; 32 cout<<endl;} 33 } 34 }b; 35 node qmod(node a,int x) 36 { 37 x--;node ans;ans=a; 38 while(x) 39 { 40 if(x&1)ans=ans*a; 41 a=a*a;x>>=1; 42 } 43 return ans; 44 } 45 int main() 46 { 47 scanf("%d%d%d%d%d",&n,&m,&t,&A,&B);int x,y; 48 for(int i=1;i<=m;++i) 49 { 50 scanf("%d%d",&x,&y); 51 add(x,y); 52 } 53 b.n=b.m=cnt; 54 for(int i=0;i<=cnt;++i) 55 for(int j=0;j<=cnt;++j) 56 { 57 if(j==(i^1)||e[i].to!=e[j].from)continue; 58 b.s[i][j]=1; 59 } 60 node ans;ans.n=1;ans.m=cnt;int sum=0; 61 for(int i=0;i<=cnt;++i) 62 if(e[i].from==A)ans.s[0][i]=1; 63 ans=ans*qmod(b,t-1); 64 for(int i=0;i<=cnt;++i) 65 if(e[i].to==B)sum=(sum+ans.s[0][i])%mod; 66 printf("%d\n",sum); 67 return 0; 68 }
生命中真正重要的不是你遭遇了什么,而是你记住了哪些事,又是如何铭记的。