BZOJ 1875: [SDOI2009]HH去散步(矩阵乘法)
首先,题意就把我们引向了矩阵乘法,注意边长m<=60,那么就按边建图,变成一个120个点的图,然后乱搞就行了。
PS:WA了N久改了3次终于A了QAQ
CODE:
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #define mod 45989 using namespace std; struct mat{ int n,m; long long a[122][122]; mat(){n=m=0; memset (a,0, sizeof (a));} int I( int _x){n=m=_x; for ( int i=1;i<=n;i++) a[i][i]=1;} }; mat operator *( const mat x, const mat y){ mat ans; ans.n=x.n;ans.m=y.m; for ( int i=1;i<=x.n;i++) for ( int j=1;j<=y.m;j++) for ( int k=1;k<=x.m;k++) (ans.a[i][j]+=x.a[i][k]*y.a[k][j])%=mod; return ans; } mat power(mat x, long long y){ mat ans;ans.I(x.n); for (;y;y>>=1){ if (y&1) ans=ans*x; x=x*x; } return ans; } struct edges{ int id,to,next; }edge[123]; int l,next[23]; int addedge( int from, int to, int id){ edge[++l]=(edges){id,to,next[from]}; next[from]=l; } int main(){ int n,m,a,b; long long t; mat x; scanf ( "%d%d%lld%d%d" ,&n,&m,&t,&a,&b); x.n=x.m=m*2; a++;b++; for ( int i=1;i<=m;i++){ int x,y; scanf ( "%d%d" ,&x,&y); x++;y++; addedge(x,y,i); addedge(y,x,i+m); } for ( int i=1;i<=n;i++) for ( int j=next[i];j;j=edge[j].next) for ( int k=next[edge[j].to];k;k=edge[k].next) if ( abs (edge[j].id-edge[k].id)!=m) x.a[edge[j].id][edge[k].id]=1; x=power(x,t-1); int q=t&1==1?1:0; long long ans=0; for ( int i=next[a];i;i=edge[i].next) for ( int j=1;j<=l;j++) if (edge[j].to==b) (ans+=x.a[edge[i].id][edge[j].id])%=mod; printf ( "%lld" ,ans); return 0; } |