hdu2157 How many ways?? (矩阵快速幂)

来源:互联网 发布:好看的推理小说知乎 编辑:程序博客网 时间:2024/06/10 00:37

题目点我点我点我


为什么会用到矩阵快速幂呢?看这篇博客的经典题目8,原链接:http://www.matrix67.com/blog/archives/276 


经典题目8 给定一个有向图,问从A点恰好走k步(允许重复经过边)到达B点的方案数mod p的值
    把给定的图转为邻接矩阵,即A(i,j)=1当且仅当存在一条边i->j。令C=A*A,那么C(i,j)=ΣA(i,k)*A(k,j),实际上就等于从点i到点j恰好经过2条边的路径数(枚举k为中转点)。类似地,C*A的第i行第j列就表示从i到j经过3条边的路径数。同理,如果要求经过k步的路径数,我们只需要二分求出A^k即可。


/* ***********************************************┆  ┏┓   ┏┓ ┆┆┏┛┻━━━┛┻┓ ┆┆┃       ┃ ┆┆┃   ━   ┃ ┆┆┃ ┳┛ ┗┳ ┃ ┆┆┃       ┃ ┆┆┃   ┻   ┃ ┆┆┗━┓ 马 ┏━┛ ┆┆  ┃ 勒 ┃  ┆      ┆  ┃ 戈 ┗━━━┓ ┆┆  ┃ 壁     ┣┓┆┆  ┃ 的草泥马  ┏┛┆┆  ┗┓┓┏━┳┓┏┛ ┆┆   ┃┫┫ ┃┫┫ ┆┆   ┗┻┛ ┗┻┛ ┆************************************************ */#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>#include <vector>#include <queue>#include <stack>#include <set>#include <map>#include <string>#include <math.h>#include <stdlib.h>using namespace std;#define rep(i,a,b) for (int i=(a),_ed=(b);i<=_ed;i++)#define per(i,a,b) for (int i=(b),_ed=(a);i>=_ed;i--)const int inf_int = 2e9;const long long inf_ll = 2e18;#define mod 1000#define ll long long#define ull unsigned long longint n;struct Mat{    int mat[25][25];};Mat operator * (Mat a,Mat b){    Mat c;    memset(c.mat,0,sizeof c.mat);    int i,j,k;    for(k=0;k<n;k++)    {        for(i=0;i<n;i++)        {            for(j=0;j<n;j++)            {                c.mat[i][j] += a.mat[i][k] * b.mat[k][j];                c.mat[i][j]=c.mat[i][j]%mod;            }        }    }    return c;}Mat operator ^ (Mat a,int k){    Mat c;    for(int i=0;i<n;i++)    {        for(int j=0;j<n;j++)        {            c.mat[i][j] = (i==j);        }    }    while(k)    {        if(k&1)c = c * a;        a = a * a;        k >>= 1;    }    return c;}int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);int a,b,t,k,m;while(~scanf("%d%d",&n,&m),n+m)    {        Mat res,ans;        memset(res.mat,0,sizeof res.mat);        for(int i=0;i<m;i++)        {            scanf("%d%d",&a,&b);            res.mat[a][b]=1;        }        scanf("%d",&t);        while(t--)        {            scanf("%d%d%d",&a,&b,&k);            ans=res^k;            cout<<ans.mat[a][b]<<endl;        }    }    return 0;}




0 0
原创粉丝点击