【雅礼同考9.9】Dream

Description

给出一张有向图( n400 n ≤ 400 ),每条边有随时间T变化的边权,公式为: si|Tpi|+ci  (si,ci,pi) s i ∗ | T − p i | + c i     ( s i , c i , p i 给 出 )
多组询问( 2e6 ≤ 2 e 6 ),问给出时间和起点,随机游走到终点n的期望距离,(走的时候不需要消耗时间)

Solution

显然的,我们只需要记录每个点期望经过次数,即可算出总的期望经过距离,
我们可以通过高斯消元解决图上定起点随机游走问题,具体的:

xi=ki,jxj+ci x i = ∑ k i , j x j + c i

ki,j k i , j 为j走到i的概率, ci c i 当i为起点是为1,其他为0,

但对于这种不定起点的,可以这么解决:
先把方程与 x x 有关项移到左边,另一边为常数c
那么,这个方程就变成了矩阵X,K,C之间的关系:

XK=C X ∗ K = C

移项:
X=CK1 X = C ∗ K − 1

于是求出K的逆矩阵,即可快速求出不同起点时,每个点的期望经过次数,

关于本题绝对值的处理方法,离线排序即可。

复杂度: O(n3+nm) O ( n 3 + n m )

Code

#include <cstdio>
#include <algorithm>
#include <iostream>
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fod(i,a,b) for(int i=a;i>=b;--i)
#define efo(i,q) for(int i=A[q];i;i=B[i][0])
#define min(q,w) ((q)>(w)?(w):(q))
#define max(q,w) ((q)<(w)?(w):(q))
using namespace std;
typedef long long LL;
const int N=500,M=2e5,mo=1e9+7;
int read(int &n)
{
    char ch=' ';int q=0,w=1;
    for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
    if(ch=='-')w=-1,ch=getchar();
    for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;
}
int m,n,ans,m1;
LL f[N*2][N];
int B[M][3],A[N],B0;
struct scB
{
    int s,p,c,S,w;
}sc[M],ak[M*10];
LL sump[N];
LL Ans[N][5],Ans1[M*10];
bool PX(scB q,scB w){return q.p<w.p;}
void link(int q,int w,int e)
{
    B[++B0][0]=A[q],A[q]=B0,B[B0][1]=w,B[B0][2]=e;
}
LL ksm(LL q,int w)
{
    LL ans=1;
    for(;w;w>>=1,q=q*q%mo)if(w&1)ans=ans*q%mo;
    return ans;
}
void Gaoxy(int n)
{
    fo(i,1,n)f[i+n][i]=1;
    fo(i,1,n)
    {
        int q=0;
        fo(j,i,n)if(f[j][i]){q=j;break;}
        if(!q)continue;
        if(q!=i)fo(j,1,n)swap(f[i][j],f[q][j]),swap(f[i+n][j],f[q+n][j]);
        LL t=ksm(f[i][i],mo-2);
        fo(j,1,n)f[i][j]=f[i][j]*t%mo,f[i+n][j]=f[i+n][j]*t%mo;
        fo(j,i+1,n)
        {
            LL t1=f[j][i]%mo;
            if(t1)fo(k,1,n)
            {
                if(f[j][k]||f[i][k])f[j][k]=(f[j][k]-t1*f[i][k])%mo;
                if(f[j+n][k]||f[i+n][k])f[j+n][k]=(f[j+n][k]-t1*f[i+n][k])%mo;
            }
        }
    }
    fod(i,n,1)if(f[i][i])
    {
        fo(j,1,i-1)
        {
            LL t=f[j][i];
            if(t)fo(k,1,n)
            {
                if(f[j][k]||f[i][k])f[j][k]=(f[j][k]-f[i][k]*t)%mo;
                if(f[j+n][k]||f[i+n][k])f[j+n][k]=(f[j+n][k]-f[i+n][k]*t)%mo;
            }
        }
    }
}
int main()
{
    int q,w,e;
    read(n),read(m),read(m1);
    fo(i,1,m)
    {
        read(q),read(w),read(e),read(sc[i].s),read(sc[i].c),read(sc[i].p);
        if(q==n){sc[i].s=1e9;continue;}
        link(q,w,e);
        sc[i].w=e;sc[i].S=q;
        // f[w][q]-=e;
        sump[q]+=e;
    }
    fo(i,1,n)sump[i]=ksm(sump[i],mo-2),f[i][i]=1;
    fo(i,1,n-1)efo(j,i)f[B[j][1]][i]=(f[B[j][1]][i]-sump[i]*B[j][2])%mo;

    Gaoxy(n);
    fo(i,1,n)fo(j,1,n)f[i][j]=f[j+n][i];
    sort(sc+1,sc+1+m,PX);
    for(;m&&sc[m].s>=1e9;--m);
    fo(i,1,m)
    {
        sc[i].c=(LL)sc[i].c*sump[sc[i].S]%mo*(LL)sc[i].w%mo;
        sc[i].s=(LL)sc[i].s*sump[sc[i].S]%mo*(LL)sc[i].w%mo;
        fo(j,1,n)
        {
            Ans[j][0]=(Ans[j][0]+f[j][sc[i].S]*(LL)sc[i].c)%mo;
            Ans[j][1]=(Ans[j][1]+f[j][sc[i].S]*(LL)sc[i].s%mo*sc[i].p)%mo;
            Ans[j][3]=(Ans[j][3]+f[j][sc[i].S]*sc[i].s)%mo;
        }
    }
    fo(i,1,m1)read(ak[i].p),read(ak[i].S),ak[i].s=i;
    sort(ak+1,ak+1+m1,PX);
    q=1;
    fo(i,1,m1)
    {
        for(;q<=m&&sc[q].p<=ak[i].p;++q)
        {
            fo(j,1,n)
            {
                Ans[j][1]=(Ans[j][1]-f[j][sc[q].S]*(LL)sc[q].s%mo*sc[q].p)%mo;
                Ans[j][2]=(Ans[j][2]+f[j][sc[q].S]*(LL)sc[q].s%mo*sc[q].p)%mo;

                Ans[j][3]=(Ans[j][3]-f[j][sc[q].S]*sc[q].s)%mo;
                Ans[j][4]=(Ans[j][4]+f[j][sc[q].S]*sc[q].s)%mo;
            }
        }
        w=ak[i].S;
        Ans1[ak[i].s]=(Ans[w][0]+Ans[w][1]-Ans[w][3]*ak[i].p-Ans[w][2]+Ans[w][4]*ak[i].p)%mo;
    }
    fo(i,1,m1)printf("%lld\n",(Ans1[i]+mo)%mo);

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值