BZOJ 1875: [SDOI2009]HH去散步

SB题。

首先容易想到没有那个不能走上一条边的限制的话我们可以直接把邻接矩阵搞出来然后矩阵快速幂

那么考虑有那个限制怎么办,仔细分析一下,其实就是走了某条边后不能再走另一条边

因此我们把每条边拆成两条,然后强制这两条边之间不能转移即可,其它的边之间的转移照旧

#include<cstdio>
#include<vector>
#include<cstring>
#define RI register int
#define CI const int&
using namespace std;
const int N=125,mod=45989;
struct edge
{
	int x,y;
}e[N]; int n,m,t,a,b,ans;
struct Matrix
{
	int n,m; long long mat[N][N];
	inline Matrix(CI N=0,CI M=0)
	{
		n=N; m=M; memset(mat,0,sizeof(mat));
	}
	inline long long* operator [] (CI x) { return mat[x]; }
	friend inline Matrix operator * (Matrix A,Matrix B)
	{
		Matrix C(A.n,B.m); RI i,j,k; for (i=0;i<C.n;++i)
		for (j=0;j<C.m;++j) for (k=0;k<A.m;++k)
		C[i][j]+=1LL*A[i][k]*B[k][j];
		for (i=0;i<C.n;++i) for (j=0;j<C.m;++j) C[i][j]%=mod; return C;
	}
	friend inline Matrix operator ^ (Matrix A,int p)
	{
		Matrix T(A.n,A.m); for (RI i=0;i<T.n;++i) T[i][i]=1;
		for (;p;p>>=1,A=A*A) if (p&1) T=T*A; return T;
	}
};
int main()
{
	RI i,j; for (scanf("%d%d%d%d%d",&n,&m,&t,&a,&b),i=0;i<m;++i)
	scanf("%d%d",&e[i<<1].x,&e[i<<1].y),e[i<<1|1].x=e[i<<1].y,e[i<<1|1].y=e[i<<1].x;
	Matrix A(m<<1,m<<1),S(m<<1,1); for (i=0;i<(m<<1);++i) for (j=0;j<(m<<1);++j)
	if ((i>>1)!=(j>>1)&&e[i].y==e[j].x) A[j][i]=1; for (i=0;i<(m<<1);++i)
	if (e[i].x==a) S[i][0]=1; if (!t) return puts(a==b?"1":"0"),0;
	for (A=A^(t-1),S=A*S,i=0;i<(m<<1);++i) if (e[i].y==b) (ans+=S[i][0])%=mod;
	return printf("%d",ans),0;
}
posted @ 2020-02-07 16:48  空気力学の詩  阅读(109)  评论(0编辑  收藏  举报