设(f[i])为(i)位置向左走一步的期望时间,那么答案就是(sum_{i=1}^mf[i])
首先(f[n]=1),设(p)为向左的概率,对于(i<n)的位置,有$$f[i]=sum_{j=1}^{infty}(j+(j-1) imes f[i+1])(1-p)^{j-1}p$$
就是说枚举一下往右走了几次,左边是走了(j)次的步数,右边是走了(j)次的概率
根据高中数学知识,这是个等比+等差数列的求和,那么推一下式子可得$$f[i]=frac{1-p}{p} imes(f[i+1]+1)+1$$
用递推可以做到(O(n))的复杂度,可以有70分
考虑一下,对于一个固定的(p),整个数列都是已知的,设(a=frac{1-p}{p}),那么有(f[n]=1,f[n-1]=2a+1,f[n-2]=2a^2+2a+1,...),我们只要可以快速求出它的后缀和,然后减一减就可以得到答案了。设(ans[j]=sum_{i=n-j+1}^n f[i]),有(ans[j]=1+2(n-1)a+2(n-2)a^2+...+2a^{n-1}),这也是一个等比+等差数列的求和,那么化一下式子可得$$ans[i]=frac{(2-i)a-i+2a^2frac{1-a^{i-1}}{1-a}}{a-1}$$
于是就可以直接求出两个后缀和相减得到答案了
注意特判(i=0)和(i=1)的情况,一个返回(0),一个返回(1)
注意特判(a=1)的情况,这种情况下(a-1)没有逆元不能直接带,打表得此时后缀和为(ans[i]=i^2),特判掉就好了
//minamoto
#include<bits/stdc++.h>
#define R register
#define ll long long
#define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
using namespace std;
const int P=1e9+7,N=1e6+5;
inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;}
inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
int ksm(R int x,R int y){
R int res=1;
for(;y;y>>=1,x=mul(x,x))if(y&1)res=mul(res,x);
return res;
}
int n,m,p,q,pi,ppi,res,now,f[N],loli;
int calc(R int n){
if(n==0)return 0;if(n==1)return 1;
if(pi==1)return mul(n,n);
res=mul(dec(2,n),pi),res=dec(res,n);
loli=mul(2,mul(pi,pi)),loli=mul(loli,dec(1,ksm(pi,n-1))),
loli=mul(loli,ksm(dec(1,pi),P-2));
return mul(add(res,loli),ksm(dec(pi,1),P-2));
}
int main(){
// freopen("testdata.in","r",stdin);
scanf("%d%d%d%d",&n,&m,&p,&q),pi=mul(p,ksm(q,P-2)),ppi=dec(1,pi);
pi=mul(ppi,ksm(pi,P-2));
printf("%d
",dec(calc(n),calc(n-m)));
return 0;
}