• 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;
    }
    //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
    

      

  • 相关阅读:
    MySQL 多列索引优化小记
    Spring MVC + Security 4 初体验(Java配置版)
    Java程序通过代理访问网络
    Spring RESTful + Redis全注解实现恶意登录保护机制
    WinSCP 中普通用户以 root 身份登录 Linux
    Linux下修改系统时区
    Git如何检出指定目录或文件
    朴素贝叶斯
    console.log 被重写覆盖以后如何恢复
    MongoDB 基础命令使用学习记录
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/6616169.html
Copyright © 2020-2023  润新知