• P2151 [SDOI2009]HH去散步


    传送门

    题目大意:问从起点走到终点,不能立刻走上一条走过的边,长度为(t)的方案数

    按点考虑会很麻烦,我们考虑按边来考虑。先把无向边给拆成两条有向边,记(dp[i][j])表示在(i)时刻走过第(j)条边到了(j)边的终点的方案数。那么它可以从(j)边的终点继续走,只要走的下一条边不是(j)的反向边就行了。很容易写出dp方程

    然而发现dp数组的第一维太大了。我们考虑一下,对于每一个第二维,它能转移到的状态是确定的,也就是说转移之间的系数矩阵是可以确定的,那么我们就可以用矩阵优化了。

    还有要注意,对于起点的时候是没有不能走哪条边的限制的,所以我们可以先枚举(1)时刻能走到哪些点,把他们作为初始矩阵即可

    //minamoto
    #include<bits/stdc++.h>
    #define op(i) ((i&1)?(i+1):(i-1))
    using namespace std;
    #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
    char buf[1<<21],*p1=buf,*p2=buf;
    int read(){
        int res,f=1;char ch;
        while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
        for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
        return res*f;
    }
    const int N=205,mod=45989;
    inline int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
    inline int mul(int x,int y){return x*y%mod;}
    int head[N],Next[N],ver[N],tot;
    inline void add_edge(int u,int v){ver[++tot]=v,Next[tot]=head[u],head[u]=tot;}
    struct Matrix{
    	int a[N][N],n,m;
    	inline void clr(){n=m=0;memset(a,0,sizeof(a));}
    	Matrix(){clr();}
    	int* operator [](const int x){return a[x];}
    	Matrix operator *(Matrix b){
    		Matrix res;res.clr(),res.n=n,res.m=b.m;
    		for(int i=1;i<=n;++i)for(int j=1;j<=b.m;++j)for(int k=1;k<=m;++k)
    		res[i][j]=add(res[i][j],mul(a[i][k],b[k][j]));
    		return res;
    	}
    	inline void operator *=(Matrix b){*this=*this*b;}
    }A,B;
    int main(){
    //	freopen("testdata.in","r",stdin);
    	int n=read(),m=read(),tt=read(),op=read()+1,ed=read()+1;
    	for(int i=1,u,v;i<=m;++i)u=read()+1,v=read()+1,add_edge(u,v),add_edge(v,u);
    	A.n=1,A.m=B.m=B.n=tot;
    	for(int j=1;j<=tot;++j){
    		int u=ver[j];
    		for(int i=head[u];i;i=Next[i])
    		if(i!=op(j))B[j][i]+=1;
    	}
    	for(int i=head[op];i;i=Next[i])A[1][i]+=1;
    	for(int i=tt-1;i;i>>=1,B*=B)if(i&1)A*=B;
    	int ans=0;
    	for(int i=head[ed];i;i=Next[i])ans=add(ans,A[1][op(i)]);
    	printf("%d
    ",ans);return 0;
    }
    
  • 相关阅读:
    Java面试集合(一)
    Java面试集合(一)
    Android-如何显示版本号并制作3秒跳转页
    Android-如何显示版本号并制作3秒跳转页
    安卓入门教程(十五)- Fragment,Service,WAMP下载
    安卓入门教程(十五)- Fragment,Service,WAMP下载
    网络开发Socket和ServerSocket
    网络开发Socket和ServerSocket
    深入浅出的Java网络通信
    深入浅出的Java网络通信
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9973538.html
Copyright © 2020-2023  润新知