[DP 矩阵快速幂] BZOJ 1875 [SDOI2009]HH去散步

一个DP

用矩阵快速幂加速

然后这个DP状态比较巧妙 以边作状态


#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#define cl(x) memset(x,0,sizeof(x))
using namespace std;

inline char nc()
{
	static char buf[100000],*p1=buf,*p2=buf;
	if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
	return *p1++;
}

inline void read(int &x){
	char c=nc(),b=1;
	for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
	for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

const int P=45989;
const int M=125;

struct Matrix{
	int a[M][M];
	int n;
	Matrix(){
	}
	Matrix(int _n,int i=0){
		n=_n; cl(a);
		if (i) for (int j=1;j<=n;j++) a[j][j]=1;
	}
	friend Matrix operator * (const Matrix &A,const Matrix &B){
		int n=A.n; Matrix ret(n);
		for (int i=1;i<=n;i++)
			for (int j=1;j<=n;j++)
				for (int k=1;k<=n;k++)
					(ret.a[i][j]+=A.a[i][k]*B.a[k][j]%P)%=P;
		return ret;
	}
}A;

struct edge{
	int u,v;
	edge(int u=0,int v=0):u(u),v(v) { }
}edges[M];
int tot=1;

int n,m,round,S,T;

inline Matrix Pow(Matrix a,int b){
	Matrix ret(a.n,1);
	for (;b;b>>=1,a=a*a)
		if (b&1)
			ret=ret*a;
	return ret;
}

int ans[M],Ans;

int main()
{
	int iu,iv;
	freopen("t.in","r",stdin);
	freopen("t.out","w",stdout);
	read(n); read(m); read(round); read(S); read(T); S++; T++;
	for (int i=1;i<=m;i++)
	{
		read(iu); read(iv); iu++; iv++; 
		edges[++tot]=edge(iu,iv); edges[++tot]=edge(iv,iu);
	}
	A=Matrix(tot);
	for (int i=2;i<=tot;i++)
	{
		for (int j=2;j<=tot;j++)
		{
			if ((i^1)==j) continue;
			if (edges[i].u==edges[j].v)
				A.a[i][j]=1;
		}
		if (edges[i].u==S)
			A.a[i][1]=1;
	}
	A=Pow(A,round);
	for (int i=1;i<=tot;i++)
	{
		ans[i]=A.a[i][1];
		if (edges[i].v==T)
			(Ans+=ans[i])%=P;
	}
	printf("%d\n",Ans);
	return 0;
}


你可能感兴趣的:([DP 矩阵快速幂] BZOJ 1875 [SDOI2009]HH去散步)