CF908D New Year and Arbitrary Arrangement
LXII.CF908D New Year and Arbitrary Arrangement
思路:
期望题果然还是恶心呀……
我们设f[i][j]表示当串中有i个a
和j个ab
时的方案数。为了方便,设A=\dfrac{P_a}{P_a+P_b},B=\dfrac{P_b}{P_a+P_b}。
显然,可以这样转移:
f[i][j]=f[i+1][j]*A+f[i][i+j]*B
因为,如果串后面加上一个a
,概率是A,并且加完后唯一的影响就是i+1;如果加入一个b
,概率是B,加完后前面每一个a
都会与这个b
形成一对ab
。
那么边界条件呢?
显然,当i+j\geq k时,只要再往后面加入一个b
,过程就停止了。
则这个的期望长度应该是:
B*\sum\limits_{a=0}^{\infty}(i+j+a)*A^a
其中,枚举的这个a是在终于搞出一个b
前,所刷出的a
的数量。
为了方便,我们设i+j=c,并用i替换a。即:
B*\sum\limits_{i=0}^{\infty}(c+i)*A^i
因为A+B=1,我们可以用(1-A)代B。
即:
(1-A)*\sum\limits_{i=0}^{\infty}(c+i)*A^i
拆开括号得
\sum\limits_{i=0}^{\infty}(c+i)*A^i-\sum\limits_{i=0}^{\infty}(c+i)*A^{i+1}
一上来直接\infty有些不直观,我们用n替换掉。
\sum\limits_{i=0}^n(c+i)*A^i-\sum\limits_{i=0}^n(c+i)*A^{i+1}
在第二个式子里面用i+1代掉i
\sum\limits_{i=0}^n(c+i)*A^i-\sum\limits_{i=1}^{n+1}(c+i-1)*A^i
将第一个\Sigma中i=0的情况和第二个\Sigma中i=n+1的情况分别提出
c+\sum\limits_{i=1}^n(c+i)*A^i-\sum\limits_{i=1}^n(c+i-1)*A^i-(c+n)*A^{n+1}
合并两个\Sigma
c+\sum\limits_{i=1}^nA^i-(c+n)*A^{n+1}
套等比数列求和公式(注意要先提出一个A使首项为1)
c+A*\dfrac{1-A^n}{1-A}-(c+n)*A^{n+1}
注意到1-A=B
c+A*\dfrac{1-A^n}{B}-(c+n)*A^{n+1}
现在,考虑n\rightarrow\infty的情况。即:
\lim\limits_{n\rightarrow\infty}c+A*\dfrac{1-A^n}{B}-(c+n)*A^{n+1}
注意到0<A<1,因此\lim\limits_{n\rightarrow\infty}A^n=0
带入发现
c+A*\dfrac{1-0}{B}-(c+n)*0
处理一下
c+\dfrac{A}{B}
注意到我们一开始的定义了吗?
A=\dfrac{P_a}{P_a+P_b},B=\dfrac{P_b}{P_a+P_b}
以及c=i+j
代入得
i+j+\dfrac{P_a}{P_b}
也就是说,边界条件就是f[i][j]=i+j+\dfrac{P_a}{P_b}(i+j\geq k)!!!
再搬出我们一开始的转移式
f[i][j]=f[i+1][j]*A+f[i][i+j]*B
完事。
哦,另外,还要思考一下答案到底是f[0][0]还是f[1][0]。
因为一开始的那些b
,无论来多少个都是没用的,因此不如直接从f[1][0]开始。(事实上,你如果把转移式代回去或者打个表的话,你会发现就有f[0][0]=f[1][0])
复杂度O(k^2+\log mod)。
代码:
#include<bits/stdc++.h>
using namespace std;
int n,a,b,A,B,f[1010][1010],c;
const int mod=1e9+7;
int ksm(int x,int y){
int z=1;
for(;y;x=(1ll*x*x)%mod,y>>=1)if(y&1)z=(1ll*z*x)%mod;
return z;
}
int dfs(int x,int y){
if(x+y>=n)return x+y+c;
if(f[x][y]!=-1)return f[x][y];
int &res=f[x][y];res=0;
(res+=1ll*dfs(x+1,y)*A%mod)%=mod;
(res+=1ll*dfs(x,x+y)*B%mod)%=mod;
return res;
}
int main(){
scanf("%d%d%d",&n,&a,&b),A=1ll*a*ksm(a+b,mod-2)%mod,B=1ll*b*ksm(a+b,mod-2)%mod,c=1ll*a*ksm(b,mod-2)%mod,memset(f,-1,sizeof(f));
printf("%d\n",dfs(1,0));
return 0;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步