题面在这里
题意
给定三个数(k,pa,pb),每次有(frac{pa}{pa+pb})的概率往后面添加一个'(a)',每次有(frac{pb}{pa+pb})的概率往后面添加一个'(b)'当出现了(k)个形如'(ab)'的子序列(不用连续)时停止。求最后的形如'(ab)'的子序列个数的期望。答案对(1e9+7)取模。
(kleq 1000)
sol
一看到(kleq 1000)马上想到(f[i][j])表示已经有(i)个(a),目前'(ab)'的子序列的个数为(j)的期望
转移:$$f[i][j]=f[i][j]+frac{pa}{pa+pb}*f[i+1][j]+frac{pb}{pa+pb}f[i][i+j]$$
但是需要考虑(bbb...bbab)(前面无限个'b')和(abbaaa...)(后面无限个'a')的情况
首先前面的'(b)'不管有多少都不需要考虑
然后考虑的就是后面无限个'a'的情况
我们注意到,如果状态(f[i][j])中的(i+jgeq k),那么只需要再加上一个'(b)'统计就会结束
那么(f[i][j])的求解实际上就是在解一个无穷级数:
[f[i][j]=frac{pb}{pa+pb}(i+j)+frac{pa}{pa+pb} imesfrac{pb}{pa+pb}(i+j+1)+(frac{pa}{pa+pb})^{2} imesfrac{pb}{pa+pb}(i+j+2)+...
]
可以化简成
[f[i][j]=i+j+frac{pa}{pb}
]
那么对于(i+jgeq k)的情况直接算出答案,其余的情况递推求解就好
代码
#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<iomanip>
#include<cstring>
#include<complex>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define mp make_pair
#define pb push_back
#define RG register
#define il inline
using namespace std;
typedef unsigned long long ull;
typedef vector<int>VI;
typedef long long ll;
typedef double dd;
const dd eps=1e-10;
const int mod=1e9+7;
const int N=1010;
const int M=90000;
il ll read(){
RG ll data=0,w=1;RG char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while(ch<='9'&&ch>='0')data=data*10+ch-48,ch=getchar();
return data*w;
}
il void file(){
//freopen("a.in","r",stdin);
//freopen("a.out","w",stdout);
}
il ll poww(ll a,ll b){RG ll ret=1;for(a%=mod;b;b>>=1,a=a*a%mod)
if(b&1)ret=ret*a%mod;return ret;}
int k,pa,pb,rev,revb,f[N][N];
il int search(int x,int y){
if(f[x][y])return f[x][y];
if(x+y>=k)return f[x][y]=(x+y+1ll*pa*revb%mod)%mod;
return f[x][y]=(1ll*pa*rev%mod*search(x+1,y)%mod+1ll*pb*rev%mod*search(x,x+y)%mod)%mod;
}
int main()
{
k=read();pa=read();pb=read();
rev=poww(pa+pb,mod-2);revb=poww(pb,mod-2);
printf("%d
",search(1,0));
return 0;
}