1. 程式人生 > >[bzoj1875] [洛谷P2151] [SDOI2009] HH去散步

[bzoj1875] [洛谷P2151] [SDOI2009] HH去散步

完全 空格 AC algorithm mar () desc init 什麽

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。
N ≤ 20,M ≤ 60,t ≤ 2^30,0 ≤ A,B

Output

一行,表示答案。

Sample Input

4 5 3 0 0

0 1

0 2

0 3

2 1

3 2

Sample Output

4


想法

數據範圍提示我用矩陣乘法。
其中每個點表示一條路而不是一個點。
然後好像沒什麽可說的了。。。。


代碼

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>

#define P 45989

using namespace std;

typedef long long ll;
const int SZ = 140;

int n,m;
struct matrix{
    ll a[SZ][SZ];
    matrix() { memset(a,0,sizeof(a)); }
    void init() { for(int i=0;i<SZ;i++) a[i][i]=1; }
    matrix operator * (const matrix &b) const{
        matrix c;
        for(int i=0;i<m;i++)
            for(int j=0;j<m;j++)
                for(int k=0;k<m;k++)
                    (c.a[i][j]+=a[i][k]*b.a[k][j])%=P;
        return c;   
    }
    matrix operator *= (const matrix &b) { return *this=*this*b; }
};
matrix Pow_mod(matrix x,ll y){
    matrix ret; ret.init();
    while(y){
        if(y&1) ret*=x;
        x*=x;
        y>>=1;  
    }
    return ret;
}

struct edge{
    int fr,to;  
}e[140];

int A,B;
ll t;

int main()
{
    int u,v;
    scanf("%d%d%lld%d%d",&n,&m,&t,&A,&B);
    for(int i=0;i<m;i++){
        scanf("%d%d",&u,&v);
        e[i*2].fr=u; e[i*2].to=v;
        e[i*2+1].fr=v; e[i*2+1].to=u;   
    }
    m*=2;
    
    matrix a,b;
    for(int i=0;i<m;i++) 
        if(e[i].fr==A) b.a[0][i]=1;
    for(int i=0;i<m;i++)
        for(int j=0;j<m;j++)
            if(e[i].to==e[j].fr){
                if(i/2==j/2) continue;
                a.a[i][j]=1;    
            }
    a=Pow_mod(a,t-1);
    b=b*a;
    
    ll ans=0;
    for(int i=0;i<m;i++)
        if(e[i].to==B) 
            (ans+=b.a[0][i])%=P;
    printf("%lld\n",ans);
    
    return 0;   
}

[bzoj1875] [洛谷P2151] [SDOI2009] HH去散步