P5165题解

xtq 的棋盘

非常好题目,使我的草稿纸旋转。

题意简介

一个长为 \(n\) 的序列,从 \(m\) 开始走,有 \(p\) 的概率往左,否则往右(在最右边必往左)。求到 \(0\) 的期望时间。

题目分析

首先我们考虑每个点到 \(0\) 的期望时间为 \(f_i\),那么有:

\[f_0=0\\ f_k=pf_{k-1}+(1-p)f_{k+1}+1\\ f_{n}=f_{n-1}+1 \]

现在我们移一下项:

\[(p-1)f_{k+1}+f_k=pf_{k-1}+1\\ \]

两边同减一个 \(pf_k\):

\[(p-1)f_{k+1}+(1-p)f_{k}=pf_{k-1}-pf_{k}+1\\ (p-1)(f_{k+1}-f_{k})=-p(f_{k}-f_{k-1})+1\\ p(f_{k}-f_{k-1})=(1-p)(f_{k+1}-f_{k})+1\\ \]

我们设 \(F_k=f_k-f_{k-1}\):

\[pF_k=(1-p)F_{k+1}+1\\ F_k=\frac{1-p}{p}F_{k+1}+\frac{1}{p}\\ F_n=f_n-f_{n-1}=1 \]

但是 \(n\le 10^9\),显然直接 dp 不可行,考虑矩阵加速,设 \(x\) 使得:

\[F_k+x=\frac{1-p}{p}(F_{k+1}+x)\\ x+\frac{1}{p}=\frac{1-p}{p}x \]

解得:\(x=\frac{1}{1-2p}\)

求得的 \(F\) 需要再做一遍前缀和才能得到 \(f\) ,所以转移如下:

\[\begin{bmatrix} S_k \\ F_k \\ \frac{1}{1-2p} \end{bmatrix} = \begin{bmatrix} 1 & \frac{1-p}{p} & \frac{1-p}{p}-1 \\ 0 & \frac{1-p}{p} & \frac{1-p}{p}-1 \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} S_{k+1} \\F_{k+1} \\ \frac{1}{1-2p} \end{bmatrix} \]

然后就可以愉快的矩阵快速幂了。

然后还有一个注意点就是上述式子中,\(p\ne \frac{1}{2}\),我们需要特别处理一下:

\[\frac{1}{2}F_k =\frac{1}{2}F_{k+1}+1\\ F_k=F_{k+1}+2\\ F_k=F_{n}+2*(n-k)=2n-2k+1\\ S_k=k(2n-k) \]

这个式子更好推,甚至用不上矩阵快速幂。

代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5+5;
const int P=1e9+7;
int n,m,pp,qq,p;
int ksm(int x,int y=P-2)
{
    int ans=1;
    while(y)
    {
        if(y&1)ans=(ans*x)%P;
        x=(x*x)%P;y/=2;
    }
    return ans;
}
struct matrix
{
    int a[10][10];
    void clear(){memset(a,0,sizeof(a));}
};
matrix operator * (matrix A,matrix B)
{
    matrix C;
    for(int i=1;i<=3;i++)
        for(int j=1;j<=3;j++)   
            C.a[i][j]=0;
    for(int i=1;i<=3;i++)
        for(int k=1;k<=3;k++)
            for(int j=1;j<=3;j++)
                C.a[i][j]=(C.a[i][j]+A.a[i][k]*B.a[k][j]%P)%P;
    return C;
}
matrix maksm(matrix A,int y)
{
    matrix ans;
    ans.a[1][1]=1;ans.a[1][2]=0;ans.a[1][3]=0;
    ans.a[2][1]=0;ans.a[2][2]=1;ans.a[2][3]=0;
    ans.a[3][1]=0;ans.a[3][2]=0;ans.a[3][3]=1;
    while(y)
    {
        if(y&1)ans=ans*A;
        A=A*A;y/=2;
    }
    return ans;
}
signed main()
{
    cin>>n>>m>>pp>>qq;
    if(pp==1&&qq==2)
    {
        cout<<(m%P)*(2*n%P-m%P+P)%P;
    }
    else
    {
        int p=pp%P*ksm(qq)%P;
        matrix A,B;
        A.clear();B.clear();
        A.a[1][1]=1;
        A.a[2][1]=1;
        A.a[3][1]=ksm((1-2*p+P)%P);
        int t=(1-p+P)%P*ksm(p)%P;
        B.a[1][1]=1;B.a[1][2]=t;B.a[1][3]=t-1;
        B.a[2][1]=0;B.a[2][2]=t;B.a[2][3]=t-1;
        B.a[3][1]=0;B.a[3][2]=0;B.a[3][3]=1;
        matrix C=maksm(B,n-m-1)*A;
        matrix D=maksm(B,n-1)*A;
        cout<<(D.a[1][1]-C.a[1][1]+P)%P;
    }

}
posted @ 2026-10-02 19:48  tidewave  阅读(11)  评论(0)    收藏  举报