zoukankan      html  css  js  c++  java
  • BZOJ 1875: [SDOI2009]HH去散步

    1875: [SDOI2009]HH去散步

    Time Limit: 20 Sec  Memory Limit: 64 MB
    Submit: 1638  Solved: 791
    [Submit][Status][Discuss]

    Description

    HH有个一成不变的习惯,喜欢饭后百步走。所谓百步走,就是散步,就是在一定的时间 内,走过一定的距离。 但是同时HH又是个喜欢变化的人,所以他不会立刻沿着刚刚走来的路走回。 又因为HH是个喜欢变化的人,所以他每天走过的路径都不完全一样,他想知道他究竟有多 少种散步的方法。 现在给你学校的地图(假设每条路的长度都是一样的都是1),问长度为t,从给定地 点A走到给定地点B共有多少条符合条件的路径

    Input

    第一行:五个整数N,M,t,A,B。其中N表示学校里的路口的个数,M表示学校里的 路的条数,t表示HH想要散步的距离,A表示散步的出发点,而B则表示散步的终点。 接下来M行,每行一组Ai,Bi,表示从路口Ai到路口Bi有一条路。数据保证Ai = Bi,但 不保证任意两个路口之间至多只有一条路相连接。 路口编号从0到N − 1。 同一行内所有数据均由一个空格隔开,行首行尾没有多余空格。没有多余空行。 答案模45989。

    Output

    一行,表示答案。

    Sample Input

    4 5 3 0 0
    0 1
    0 2
    0 3
    2 1
    3 2

    Sample Output

    4

    HINT

    对于30%的数据,N ≤ 4,M ≤ 10,t ≤ 10。 对于100%的数据,N ≤ 20,M ≤ 60,t ≤ 2^30,0 ≤ A,B

    Source

    Day1

    分析:

    不错的转化...

    我们第一想法大概就是矩阵优化DP,但是发现貌似过不了,所以我们可以考虑用边作为状态来DP...

    $f[i][j]$代表从边$i$走向边$j$的方案数...

    代码:

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    //by NeighThorn
    using namespace std;
    
    const int maxn=120+5,mod=45989;
    
    int n,m,t,A,B,ans,cnt,hd[maxn],to[maxn],pre[maxn],nxt[maxn];
    
    struct M{
    	
    	int a[maxn][maxn];
    	
    	inline void init(void){
    		memset(a,0,sizeof(a));
    	}
    	
    	inline void initone(void){
    		memset(a,0,sizeof(a));
    		for(int i=0;i<cnt;i++) a[i][i]=1;
    	}
    	
    	friend M operator * (M x,M y){
    		M res;res.init();
    		for(int i=0;i<cnt;i++)
    			for(int j=0;j<cnt;j++)
    				for(int k=0;k<cnt;k++)
    					(res.a[i][j]+=1LL*x.a[i][k]*y.a[k][j]%mod)%=mod;
    		return res;
    	}
    	
    }pri;
    
    inline M power(M x,int y){
    	M res;res.initone();
    	while(y){
    		if(y&1)
    			res=res*x;
    		x=x*x,y>>=1;
    	}
    	return res;
    }
    
    inline void add(int x,int y){
    	to[cnt]=y;pre[cnt]=x;nxt[cnt]=hd[x];hd[x]=cnt++;
    }
    
    signed main(void){
    	scanf("%d%d%d%d%d",&n,&m,&t,&A,&B);
    	cnt=0;pri.init();memset(hd,-1,sizeof(hd));
    	if(t==0) return puts(A==B?"1":"0"),0; 
    	for(int i=1,x,y;i<=m;i++)
    		scanf("%d%d",&x,&y),add(x,y),add(y,x);
    	for(int i=0;i<cnt;i++)
    		for(int j=0;j<cnt;j++)
    			if(i!=j&&(i^j)!=1&&to[i]==pre[j])
    				pri.a[i][j]++;
    	pri=power(pri,t-1);
    	for(int i=hd[A];i!=-1;i=nxt[i])
    		for(int j=hd[B];j!=-1;j=nxt[j])
    			ans=(ans+pri.a[i][j^1])%mod;
    	printf("%d
    ",ans);
    	return 0;
    }	
    

      


    By NeighThorn

  • 相关阅读:
    判断用户 是用的电脑还是手机 判断 是安卓还是IOS
    特殊符号
    如何在 ajax 外拿到 ajax 的数据???和ajax的参数
    事件(只有事件 没有其他)
    c3 新特性
    jquery 操作属性[选择器为主]
    按字母排序,sql语句查询法
    ubuntu12.04安装lamp的简单lamp
    Ubuntu 下傻瓜式安装配置lamp环境
    万能HTML编辑框 CuteEditor 使用详解
  • 原文地址:https://www.cnblogs.com/neighthorn/p/6656336.html
Copyright © 2011-2022 走看看