bzoj1875: [SDOI2009]HH去散步

来源:互联网 发布:淘宝网小商品 编辑:程序博客网 时间:2024/05/16 07:44

传送门
首先我们发现t特别大,n特别小。
这启示我们用矩阵乘法做。
设f[i][j]表示从i到j的方案数。
显然这是支持矩阵乘法的。
时间复杂度O(N^3*logT)

#include<cmath>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<cstdlib>#define ll long longusing namespace std;int n,m,T,s,t,x,y,ans,tot=2,head[130];struct matrix{    int a[130][130];    void clear(){memset(a,0,sizeof(a));}}ppp,qqq,rrr,sss;matrix mult(matrix x,matrix y){    matrix z;    z.clear();    for (int i=0;i<tot;i++)        for (int j=0;j<tot;j++)            for (int k=0;k<tot;k++)                z.a[i][j]=(z.a[i][j]+x.a[i][k]*y.a[k][j])%45989;    return z;}matrix pow(matrix c,int x){    matrix b;    b.clear();    for (int i=0;i<tot;i++) b.a[i][i]=1;    while (x){        if (x&1) b=mult(b,c);        c=mult(c,c);        x/=2;    }    return b;}struct edge{int to,next;}e[150];inline void add(int x,int y){    e[tot].to=y;    e[tot].next=head[x];    head[x]=tot;    tot++;}int main(){    memset(head,-1,sizeof(head));     scanf("%d%d%d%d%d",&n,&m,&T,&s,&t);    for (int i=1;i<=m;i++){        scanf("%d%d",&x,&y);        add(x,y);        add(y,x);    }    for (int i=head[s];i!=-1;i=e[i].next) ppp.a[0][i]=1;    for (int i=2;i<tot;i++){        int v=e[i].to;        for (int j=head[v];j!=-1;j=e[j].next)            if (i!=(j^1)) qqq.a[i][j]=1;    }    rrr=pow(qqq,T-1);    sss=mult(ppp,rrr);    ans=0;    for (int i=0;i<tot;i++)        if (e[i].to==t) ans=(ans+sss.a[0][i])%45989;    printf("%d",ans);}
原创粉丝点击