您的位置:首页 > 其它

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

2016-01-02 21:37 351 查看
这道题得到了学长的助攻,其实就是一个马尔科夫链,算出一步转移矩阵进行矩阵快速幂就行了,无奈手残

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

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

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

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

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

f_{t+1,y}=\sum_{x,x->y}{\frac{f_{t,x}}{Out_x}},Out_xf​t+1,y​​=∑​x,x−>y​​​Out​x​​​​f​t,x​​​​,Out​x​​表示xx的出度.

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

复杂度是O(QN^3\log t)O(QN​3​​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("\n");
}
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: