Codeforces908D. New Year and Arbitrary Arrangement【期望dp】

本文探讨了一种特定的概率序列问题,即在给定概率条件下,求解ab子序列出现k次时的期望次数。通过定义状态转移方程,并利用差比数列方法计算终止状态值,最终得出了解决方案。
题目大意:

给定整数k,pa,pb。
初始有一个空序列,每次往末尾添加一个字符,有pa/(pa+pb)的概率添加a,有pb/(pa+pb)的概率添加b。
当ab作为子序列出现了至少k次的时候停止,问此时ab子序列出现次数的期望。对10^9+7取模。
1<=k<=1000,1<=pa,pb<=10^6。

解题思路:

f[i][j]f[i][j]f[i][j]表示当前有 iii 个a,jjj 个ab子序列到停止时的期望,那么
f[i][j]=papa+pbf[i+1][j]+pbpa+pbf[i][j+i]f[i][j]=\frac{pa}{pa+pb}f[i+1][j]+\frac{pb}{pa+pb}f[i][j+i]f[i][j]=pa+pbpaf[i+1][j]+pa+pbpbf[i][j+i]

其实以上都不是重点,重点在于定下目标状态和终止状态值。

1.目标状态:
如果我们把目标状态定为f[0][0]f[0][0]f[0][0],那么
f[0][0]=(pa∗f[1][0]+pb∗f[0][0])/(pa+pb)f[0][0]=(pa*f[1][0]+pb*f[0][0])/(pa+pb)f[0][0]=(paf[1][0]+pbf[0][0])/(pa+pb)会死循环,相当于一开始会有无穷多个b:bbbbb…….bbbbaababa…
但也可推出 f[0][0]=f[1][0]f[0][0]=f[1][0]f[0][0]=f[1][0],所以目标状态应为 f[1][0]f[1][0]f[1][0]

2.终止状态:
i+j≥ki+j\ge ki+jk 时,再出现一个b就会停止,所以当 i+j≥ki+j\ge ki+jk
f[i][j]=(i+j)B+(i+j+1)AB+(i+j+2)A2B+...f[i][j]=(i+j)B+(i+j+1)AB+(i+j+2)A^2B+...f[i][j]=(i+j)B+(i+j+1)AB+(i+j+2)A2B+...用差比数列的方法计算可得f[i][j]=i+j+papbf[i][j]=i+j+\frac{pa}{pb}f[i][j]=i+j+pbpa

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int getint()
{
    int i=0,f=1;char c;
    for(c=getchar();(c!='-')&&(c<'0'||c>'9');c=getchar());
    if(c=='-')c=getchar(),f=-1;
    for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
    return i*f;
}
const int N=1005,mod=1e9+7;
int k;ll pa,pb,inv_pb,f[N][N];
ll Pow(ll x,int y)
{
	ll res=1;
	for(;y;y>>=1,x=x*x%mod)
		if(y&1)res=res*x%mod;
	return res;
}
ll dfs(int i,int j)
{
	if(i+j>=k)return (i+j+pa*inv_pb)%mod;
	if(f[i][j]!=-1)return f[i][j];
	return f[i][j]=(dfs(i+1,j)*pa+dfs(i,j+i)*pb)%mod;
}
int main()
{
	//freopen("lx.in","r",stdin);
	memset(f,-1,sizeof(f));
	k=getint(),pa=getint(),pb=getint();
	pa=pa*Pow(pa+pb,mod-2)%mod,pb=(1-pa+mod)%mod,inv_pb=Pow(pb,mod-2);
	printf("%lld\n",dfs(1,0));
	return 0;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值