[bzoj1875][SDOI2009]HH去散步

来源:互联网 发布:伪娘被肛哭 知乎 编辑:程序博客网 时间:2024/05/16 08:31

题目描述

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

矩阵乘法

如果没有不能立刻走走过的路的限制是很水的矩阵乘法。
有了之后也不难,把f[i,n]表示第n个时刻在点i的方案数改成f[i,n]表示第n个时刻在边i的终点的方案数即可。
由于作死玩结构体重载运算符所以跑的飞慢。

#include<cstdio>#include<algorithm>#include<stack>#define fo(i,a,b) for(i=a;i<=b;i++)using namespace std;typedef int ll;const int mo=45989;int from[200],go[200];stack<int> sta;int i,j,k,l,s,t,n,m,tot,ans;struct matrix{    ll a[200][200];    friend matrix operator *(matrix a,matrix b){        matrix c;        int i,j,k;        fo(i,1,tot)            fo(j,1,tot) c.a[i][j]=0;        fo(k,1,tot)            fo(i,1,tot)                fo(j,1,tot)                    c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j]%mo)%mo;        return c;    }};matrix a,dis,c,one,tt;int main(){    scanf("%d%d%d%d%d",&n,&m,&l,&s,&t);    s++;t++;    tot=1;    from[1]=0;go[1]=s;    fo(i,1,m){        scanf("%d%d",&j,&k);        j++;k++;        from[++tot]=j;go[tot]=k;        from[++tot]=k;go[tot]=j;    }    fo(i,1,tot)        fo(j,1,tot)            if (i!=j&&(j^1)!=i&&go[j]==from[i]) dis.a[j][i]=1;    a.a[1][1]=1;    fo(i,1,tot) one.a[i][i]=1;    while (l){        sta.push(l%2);        l/=2;    }    tt=one;    while (!sta.empty()){        tt=tt*tt;        if (sta.top()==1) tt=tt*dis;        sta.pop();    }    dis=tt;    c=a*dis;    fo(i,1,tot)        if (go[i]==t) ans=(ans+c.a[1][i])%mo;    printf("%d\n",ans);}
0 0
原创粉丝点击