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;
}
}

浙公网安备 33010602011771号