HDU 5607 graph 矩阵快速幂 + 快速幂

这道题得到了学长的助攻,其实就是一个马尔科夫链,算出一步转移矩阵进行矩阵快速幂就行了,无奈手残

这是我第一回写矩阵快速幂,写的各种毛病,等到调完了已经8点44了,交了一发,返回PE,(发现是少了换行)再想交的时候已经开始hack了

真是TMD。。。。。。。,然后rejudge完了之后再HDOJ上瞬间AC,真是。。。狗了,只能是自己手残

手残,手残,手残(重要的事情说三遍)

思路 :(杭电官方题解,我就不班门弄斧了。。QAQ)

考虑dpdp,用f_{t,x}ft,x​​表示第tt秒在xx的概率,初始时f_{0,u}=1f0,u​​=1.

f_{t+1,y}=sum_{x,x->y}{frac{f_{t,x}}{Out_x}},Out_xft+1,y​​=x,x>y​​Outx​​ft,x​​​​,Outx​​表示xx的出度.

因为tt很大,而且发现每次的转移都是相同的,所以直接矩乘就好了.

复杂度是O(QN^3log t)O(QN3​​logt).

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<cstdlib>
#include<vector>
#include<queue>
using namespace std;
typedef long long LL;
const int maxn=50+5;
const LL mod=1e9+7;
vector<int>g[maxn];
int n,m;
LL xx[maxn][maxn],yy[maxn][maxn];
struct mat
{
    LL x[maxn][maxn],y[maxn][maxn];
} o,res;
mat mul(mat a,mat b)
{
    mat temp;
    for(int i=1; i<=n; ++i)
        for(int j=1; j<=n; ++j)
        {
            temp.x[i][j]=0;
            temp.y[i][j]=1;
            for(int k=1; k<=n; ++k)
            {
                LL t1=a.x[i][k]*b.x[k][j]%mod;
                LL t2=a.y[i][k]*b.y[k][j]%mod;
                temp.x[i][j]=(temp.x[i][j]*t2%mod+temp.y[i][j]*t1%mod)%mod;
                temp.y[i][j]=(temp.y[i][j]*t2)%mod;
            }
        }
    return temp;
}
void cal(int c)
{
    for(int i=1; i<=n; ++i)
        for(int j=1; j<=n; ++j)
        {
            o.x[i][j]=xx[i][j];
            o.y[i][j]=yy[i][j];
            res.x[i][j]=0,res.y[i][j]=1;
        }
    for(int i=1; i<=n; ++i)
        res.x[i][i]=1;
    while(c)
    {
        if(c&1)
            res=mul(res,o);
        c>>=1;
        o=mul(o,o);
    }
}
LL getans(LL x,LL y)
{
    int c=1e9+5;
    LL r=1;
    while(c)
    {
        if(c&1)
            r=(r*y)%mod;
        c>>=1;
        y=(y*y)%mod;
    }
    r=(x%mod*r%mod);
    return r;
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        memset(xx,0,sizeof(xx));
        for(int i=1; i<=n; i++)
            for(int j=1; j<=n; j++)
                yy[i][j]=1;
        for(int i=1; i<=n; ++i)
            g[i].clear();
        for(int i=0; i<m; ++i)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            g[u].push_back(v);
        }
        for(int i=1; i<=n; ++i)
        {
            for(int j=0; j<g[i].size(); ++j)
                xx[i][g[i][j]]=1,yy[i][g[i][j]]=g[i].size();
        }
        int q;
        scanf("%d",&q);
        while(q--)
        {
            int u,k;
            scanf("%d%d",&u,&k);
            cal(k);
            for(int i=1; i<=n; i++)
                printf("%I64d ",getans(res.x[u][i],res.y[u][i]));
            printf("
");
        }
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/shuguangzw/p/5095334.html