[CF908D]New Year and Arbitrary Arrangement

题面在这里

题意

给定三个数\(k,pa,pb\),每次有\(\frac{pa}{pa+pb}\)的概率往后面添加一个'\(a\)',每次有\(\frac{pb}{pa+pb}\)的概率往后面添加一个'\(b\)'当出现了\(k\)个形如'\(ab\)'的子序列(不用连续)时停止。求最后的形如'\(ab\)'的子序列个数的期望。答案对\(1e9+7\)取模。
\(k\leq 1000\)

sol

一看到\(k\leq 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+j\geq k\),那么只需要再加上一个'\(b\)'统计就会结束
那么\(f[i][j]\)的求解实际上就是在解一个无穷级数:

\[f[i][j]=\frac{pb}{pa+pb}(i+j)+\frac{pa}{pa+pb}\times\frac{pb}{pa+pb}(i+j+1)+(\frac{pa}{pa+pb})^{2}\times\frac{pb}{pa+pb}(i+j+2)+... \]

可以化简成

\[f[i][j]=i+j+\frac{pa}{pb} \]

那么对于\(i+j\geq 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\n",search(1,0));
    return 0;
}

posted @ 2018-02-09 22:35  cjfdf  阅读(239)  评论(0编辑  收藏  举报