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−>yOutxft,x,Outx表示xx的出度.
因为tt很大,而且发现每次的转移都是相同的,所以直接矩乘就好了.
复杂度是O(QN^3\log t)O(QN3logt).
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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("\n"); } } return 0; }