[SDOI2009]HH去散步

[SDOI2009]HH去散步

题目描述

HH有个一成不变的习惯,喜欢饭后百步走。所谓百步走,就是散步,就是在一定的时间 内,走过一定的距离。 但是同时HH又是个喜欢变化的人,所以他不会立刻沿着刚刚走来的路走回。 又因为HH是个喜欢变化的人,所以他每天走过的路径都不完全一样,他想知道他究竟有多 少种散步的方法。

现在给你学校的地图(假设每条路的长度都是一样的都是1),问长度为t,从给定地 点A走到给定地点B共有多少条符合条件的路径

输入输出格式

输入格式:

第一行:五个整数N,M,t,A,B。其中N表示学校里的路口的个数,M表示学校里的 路的条数,t表示HH想要散步的距离,A表示散步的出发点,而B则表示散步的终点。

接下来M行,每行一组Ai,Bi,表示从路口Ai到路口Bi有一条路。数据保证Ai != Bi,但 不保证任意两个路口之间至多只有一条路相连接。 路口编号从0到N − 1。 同一行内所有数据均由一个空格隔开,行首行尾没有多余空格。没有多余空行。 答案模45989。

输出格式:

一行,表示答案。

输入输出样例

输入样例#1: 
4 5 3 0 0
0 1
0 2
0 3
2 1
3 2
输出样例#1: 
4

说明

对于30%的数据,N ≤ 4,M ≤ 10,t ≤ 10。

对于100%的数据,N ≤ 50,M ≤ 60,t ≤ 2^30,0 ≤ A,B

思路

和迷路那道题相似,不过这一次我们不可以来回走

于是我们只好以x边的起点,y边的终点构造矩阵

然后就是同样的套路了,只不过我们需要在初始的时候加一个两条边是否为同一条边的条件,并且将t--,原因

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define rep(i,a,b) for(long long i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const ll mod=45989ll;
ll n,mm,s,e,t,to[200],tot=-1,sum;
struct zlk{ll M[200][200];}a,ans;
zlk mul(zlk x,zlk y){
    zlk rk;
    rep(i,0,tot) rep(j,0,tot) rk.M[i][j]=0;
    rep(i,0,tot) rep(j,0,tot) rep(k,0,tot){
    	rk.M[i][j]+=x.M[i][k]*y.M[k][j];rk.M[i][j]%=mod;
	}
    return rk;
}
void ksm(){
    while(t){
        if(t&1) ans=mul(ans,a);
        a=mul(a,a);
        t>>=1;
    }
}
int main(){
    scanf("%lld%lld%lld%lld%lld",&n,&mm,&t,&s,&e); s++; e++; t--;
    rep(i,1,mm){
        ll x,y; scanf("%lld%lld",&x,&y);
        x++; y++;
        to[++tot]=y; to[++tot]=x;
    }
    rep(i,0,tot) rep(j,0,tot) if(to[i]==to[(j^1)] && i!=(j^1)) a.M[i][j]=1;
    rep(i,0,tot) ans.M[i][i]=1;
    ksm();
    rep(i,0,tot) rep(j,0,tot) if(to[(i^1)]==s && to[j]==e) sum=(sum+ans.M[i][j])%mod;
    printf("%lld",sum);
    return 0;
}

  

原文地址:https://www.cnblogs.com/handsome-zlk/p/10551533.html