gym-102861-A(概率DP)

题意

每 包 贴 纸 拆 开 后 可 获 得 [ a , b ] 张 ( 均 匀 分 布 ) , 现 有 一 本 容 量 为 n 的 相 册 , 现 需 填 满 相 册 , 求 拆 开 包 数 的 期 望 。 每包贴纸拆开后可获得[a,b]张(均匀分布),现有一本容量为n的相册,现需填满相册,求拆开包数的期望。 [a,b]n,

题解

令 d p [ i ] : 获 得 i 张 卡 牌 所 需 的 包 数 。 令dp[i]:获得i张卡牌所需的包数。 dp[i]i
拆 开 1 包 至 少 获 得 a 张 贴 纸 , 显 然 d p [ 1 ] ∽ d p [ a ] 的 值 均 为 1 。 拆开1包至少获得a张贴纸,显然dp[1] \backsim dp[a]的值均为1。 1adp[1]dp[a]1

对 于 d p [ x ] , 即 为 d p [ x − b ] ∽ d p [ x − a ] 的 均 值 + 1 。 ( 拆 开 前 一 包 时 , 获 得 a ∽ b 张 的 概 率 均 为 1 b − a + 1 ) 对于dp[x],即为dp[x-b] \backsim dp[x-a]的均值+1。(拆开前一包时,获得a \backsim b 张的概率均为\frac{1}{b-a+1}) dp[x],dp[xb]dp[xa]+1abba+11

即 : 即:
d p [ x ] = d p [ x − b ] + d p [ x − b + 1 ] + ⋯ + d p [ x − a − 1 ] + d p [ x − a ] b − a + 1 + 1 dp[x]=\frac{dp[x-b]+dp[x-b+1]+\cdots +dp[x-a-1]+dp[x-a]}{b-a+1}+1 dp[x]=ba+1dp[xb]+dp[xb+1]++dp[xa1]+dp[xa]+1
d p [ x ] = p r e [ x − a ] − p r e [ x − b − 1 ] b − a + 1 + 1 dp[x]=\frac{pre[x-a]-pre[x-b-1]}{b-a+1}+1 dp[x]=ba+1pre[xa]pre[xb1]+1
接 下 来 只 需 循 环 着 跑 一 遍 求 d p [ n ] 即 可 接下来只需循环着跑一遍求dp[n]即可 dp[n]

此 外 , 当 a = 0 时 , 公 式 左 右 均 出 现 了 d p [ x ] , 解 方 程 即 可 此外,当a=0时,公式左右均出现了dp[x],解方程即可 a=0dp[x]
d p [ x ] = d p [ x − b ] + d p [ x − b + 1 ] + ⋯ + d p [ x − 1 ] + d p [ x − 0 ] b + 1 + 1 dp[x]=\frac{dp[x-b]+dp[x-b+1]+\cdots +dp[x-1]+dp[x-0]}{b+1}+1 dp[x]=b+1dp[xb]+dp[xb+1]++dp[x1]+dp[x0]+1
d p [ x ] − d p [ x ] b + 1 = d p [ x − b ] + d p [ x − b + 1 ] + ⋯ + d p [ x − 1 ] b + 1 + 1 dp[x]-\frac{dp[x]}{b+1}=\frac{dp[x-b]+dp[x-b+1]+\cdots +dp[x-1]}{b+1}+1 dp[x]b+1dp[x]=b+1dp[xb]+dp[xb+1]++dp[x1]+1
b ∗ d p [ x ] b + 1 = d p [ x − b ] + d p [ x − b + 1 ] + ⋯ + d p [ x − 1 ] + b + 1 b + 1 \frac{b*dp[x]}{b+1}=\frac{dp[x-b]+dp[x-b+1]+\cdots +dp[x-1]+b+1}{b+1} b+1bdp[x]=b+1dp[xb]+dp[xb+1]++dp[x1]+b+1
d p [ x ] = d p [ x − b ] + d p [ x − b + 1 ] + ⋯ + d p [ x − 1 ] + b + 1 b dp[x]=\frac{ {dp[x-b]+dp[x-b+1]+\cdots +dp[x-1]}+b+1}{b} dp[x]=bdp[xb]+dp[xb+1]++dp[x1]+b+1
d p [ x ] = p r e [ x − 1 ] − p r e [ x − b − 1 ] + b + 1 b dp[x]=\frac{ {pre[x-1]-pre[x-b-1]}+b+1}{b} dp[x]=bpre[x1]pre[xb1]+b+1

代码

#include<bits/stdc++.h>
using namespace std;
double dp[1006000],pre[1006000];//pre维护dp的前缀和
int n,a,b;
int main()
{
    
    
	cin>>n>>a>>b;
	for(int i=1;i<a;i++)dp[i]=1.0,pre[i]=pre[i-1]+dp[i];//每包打开获得至少 l 张贴纸,所以获得 1~a-1 张贴纸只需打开1包
	if(a>0)
	{
    
    
		for(int i=a;i<=n;i++)
		{
    
    
			dp[i]=1.0*(pre[i-a]-pre[max(0,i-b-1)])/(b-a+1)+1;
			//打开一包获得 a~b 张贴纸的概率相等,所以获得i张贴纸需要(dp[i-b]~dp[i-a])/(b-a+1)+1包
			//pre求解dp[i-b]~dp[i-a]的累加和,i-r-1<0时当成pre[0]来看,即包数为0包;
			pre[i]=pre[i-1]+dp[i];
		}
	}
	else//a=0时的情况
	{
    
    
		for(int i=1;i<=n;i++)
		{
    
    
			dp[i]=(1.0*(pre[i-1]-pre[max(0,i-b-1)])+b+1)/b;
			pre[i]=pre[i-1]+dp[i];
		}
	}
	printf("%.6lf",dp[n]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/dyy7777777/article/details/113094962
今日推荐