BZOJ1875 [SDOI2009]HH去散步
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。
本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!
题目链接:BZOJ1875
正解:矩乘快速幂
解题报告:
考虑如果没有那个不能往回走的约束条件的话,就是建出矩阵,直接矩乘快速幂就好了。
但是没有办法处理往回走的情况,因为我们不希望有走过去再走回来这种情况的发生,所以有一个比较巧妙的方法就是按边建矩阵,把每条边拆成$2$条然后同样的做法就好了。
注意想清楚,应该是矩阵的$t-1$次方就好了。
//It is made by ljh2000 //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。 #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> #include <ctime> #include <vector> #include <queue> #include <map> #include <set> #include <complex> #include <bitset> using namespace std; typedef long long LL; typedef long double LB; const double pi = acos(-1); const int MAXN = 22; const int MAXM = 150; const int mod = 45989; int n,m,t,S,T,ecnt,first[MAXN],to[MAXM],next[MAXM],ans,B[MAXM],lin[MAXM]; struct Matrix{ int s[121][121]; }A,tmp,Kong; struct edge{ int x,y; }e[MAXM]; inline void link(int x,int y){ next[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=y; } inline int getint(){ int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar(); if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w; } inline Matrix operator * (const Matrix &q,const Matrix &qq) { tmp=Kong; for(int i=0;i<=ecnt;i++) for(int j=0;j<=ecnt;j++) for(int k=0;k<=ecnt;k++) tmp.s[i][j]+=q.s[i][k]*qq.s[k][j]%mod,tmp.s[i][j]%=mod; return tmp; } inline void cheng(){ for(int i=0;i<=ecnt;i++) lin[i]=0; for(int i=0;i<=ecnt;i++) { for(int j=0;j<=ecnt;j++) { lin[i]+=B[j]*A.s[j][i]%mod; lin[i]%=mod; } } for(int i=0;i<=ecnt;i++) B[i]=lin[i]; } inline void fast_pow(int y){ while(y>0) { if(y&1) cheng(); A=A*A; y>>=1; } } inline void work(){ n=getint(); m=getint(); t=getint(); S=getint()+1; T=getint()+1; memset(first,-1,sizeof(first)); ecnt=-1; int x,y; for(int i=1;i<=m;i++) { x=getint()+1; y=getint()+1; e[(i-1)<<1].x=x; e[(i-1)<<1].y=y; e[(i-1)<<1|1].x=y; e[(i-1)<<1|1].y=x; link(x,y); link(y,x); } for(int i=0;i<=ecnt;i++) { x=e[i].y; for(int j=first[x];j!=-1;j=next[j]) { if(j==(i^1)) continue; A.s[i][j]=1; } } for(int i=0;i<=ecnt;i++) if(e[i].x==S) B[i]=1; fast_pow(t-1); for(int i=0;i<=ecnt;i++) if(e[i].y==T) ans+=B[i],ans%=mod; printf("%d",ans); } int main() { #ifndef ONLINE_JUDGE freopen("1875.in","r",stdin); freopen("1875.out","w",stdout); #endif work(); return 0; } //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!