BZOJ 1875 [SDOI2009]HH去散步 ——动态规划 矩阵乘法

发现t非常大,所以大概就是快速幂一类的问题了,

然后根据k^3logn算了算,发现k大约是边数的时候复杂度比较合适。

发现比较麻烦的就是前驱的记录,所以直接把边看做点,不能走反向边,但是可以走重边,然后t--

之后弄出状态转移矩阵递推即可。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
  
#define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i)
#define ll long long
  
const ll md=45989;
int n,m,t,A,B;
  
int h[150],to[150],ne[150],fr[150],en=0,ans;
void add(int a,int b)
{to[en]=b;ne[en]=h[a];fr[en]=a;h[a]=en++;}
  
struct Matrix{
    ll x[125][125];
    void init(){memset(x,0,sizeof x);}
    Matrix operator * (Matrix y) {
        Matrix ret; ret.init();
        F(i,0,en-1) F(k,0,en-1)
        {
            F(j,0,en-1) ret.x[i][k]+=x[i][j]*y.x[j][k];
            ret.x[i][k]%=md;
        }
        return ret;
    }
}a,b;
  
int main()
{
    memset(h,-1,sizeof h);
    scanf("%d%d%d%d%d",&n,&m,&t,&A,&B);t--;
    a.init(); b.init();
    F(i,1,m)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        add(a,b);add(b,a);
    }
    F(i,0,en-1)
    {
        int st=to[i];
        for (int j=h[st];j>=0;j=ne[j])
            if ((i^1)!=j)b.x[i][j]++;
    }
    for (int i=h[A];i>=0;i=ne[i])
        a.x[0][i]=1;
    while (t)
    {
        if (t&1) a=a*b;
        b=b*b;
        t>>=1;
    }
    F(i,0,en-1) if (to[i]==B) (ans+=a.x[0][i])%=md;
    printf("%d\n",ans);
}

  

posted @ 2017-03-01 23:13  SfailSth  阅读(240)  评论(0编辑  收藏  举报