[CSP-S模拟测试]:简单的期望(DP)

题目描述

从前有个变量$x$,它的初始值已给出。
你会依次执行$n$次操作,每次操作有$p\%$的概率令$x=x\times 2$,$(100−p)\%$的概率令$x=x+1$。
假设最后得到的值为$w$,令$d$为$w$的质因数分解中$2$的次数,求$d$的期望。


输入格式

从文件$exp.in$中读入数据。
第一行三个整数$x,n,p$,含义见题目描述。


输出格式

输出到文件$exp.out$中。
一行一个实数,表示$d$的期望。
如果你的答案与标准答案的误差不超过$10^{−6}$,则判定为正确。


样例

样例输入1:

1 1 50

样例输出1:

1.0000000000

样例输入2:

5 3 0

样例输出2:

3.0000000000

样例输入3:

5 3 25

样例输出3:

1.9218750000


数据范围与提示

对于$20\%$的数据,$n\leqslant 20$;
对于$30\%$的数据,$n\leqslant 50$;
对于$50\%$的数据,$n\leqslant 100$;
对于$100\%$的数据,$x\leqslant 10^9,n\leqslant 200,0\leqslant p\leqslant 100$。


题解

首先,质因数分解中$2$的个数即为二进制表示下末尾$0$的个数。

考虑$DP$,设$dp[i][s][j][0/1]$表示进行第$i$次操作后,当前数的二进制表示后$8$位为$s$,第九位为$0/1$,从第九位开始往前连续$j$位相同的概率。

先来解释后$8$位的原因,因为至少要$2^8+1$次操作才可以向$9$进位,而操作数只有$200$,所以不会对答案造成贡献。

再来解释$j$的用途,假如后$8$位都是$1$第九位也是$1$,那么我们在进行$+1$的操作后会变成$1000……$,而$j$是为了计算出这个$1$的位置。

转移一共有$8$个,不再一一赘述,具体可以看代码。

时间复杂度:$\Theta(2^8n^2)$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

#include<bits/stdc++.h>
using namespace std;
int X,N,P,mx;
double gl1,gl2;
double dp[201][257][300][2];
double ans;
void pre_work()
{
	int flag=X>>8,sum=0;
	for(int i=flag&1;(flag&1)==i&&flag;sum++)flag>>=1;
	if(!sum)sum++;mx=N+sum;
	dp[0][X&255][sum][(X>>8)&1]=1;
}
int judge(int x)
{
	int res=0;
	while(!(x&1)){res++;x>>=1;}
	return res;
}
int main()
{
	scanf("%d%d%d",&X,&N,&P);
	gl1=(double)P/100;
	gl2=(double)(100-P)/100;
	pre_work();
	for(int i=0;i<N;i++)
		for(int s=0;s<256;s++)
			for(int j=1;j<=mx;j++)
			{
				if(!(((s<<1)&256)>>8))dp[i+1][(s<<1)&255][j+1][0]=dp[i+1][(s<<1)&255][j+1][0]+dp[i][s][j][0]*gl1;
				else dp[i+1][(s<<1)&255][1][1]=dp[i+1][(s<<1)&255][1][1]+dp[i][s][j][0]*gl1;
				if(((s<<1)&256)>>8)dp[i+1][(s<<1)&255][j+1][1]=dp[i+1][(s<<1)&255][j+1][1]+dp[i][s][j][1]*gl1;
				else dp[i+1][(s<<1)&255][1][0]=dp[i+1][(s<<1)&255][1][0]+dp[i][s][j][1]*gl1;
				if(s==255)dp[i+1][0][1][1]=dp[i+1][0][1][1]+dp[i][255][j][0]*gl2;
				else dp[i+1][s+1][j][0]=dp[i+1][s+1][j][0]+dp[i][s][j][0]*gl2;
				if(s==255)dp[i+1][0][j][0]=dp[i+1][0][j][0]+dp[i][255][j][1]*gl2;
				else dp[i+1][s+1][j][1]=dp[i+1][s+1][j][1]+dp[i][s][j][1]*gl2;
			}
	for(int s=1;s<256;s++)
		for(int j=1;j<=mx;j++)
			ans+=(dp[N][s][j][0]+dp[N][s][j][1])*judge(s);
	for(int j=1;j<=mx;j++)ans+=dp[N][0][j][0]*(j+8)+dp[N][0][j][1]*8;
	printf("%.6lf",ans);
	return 0;
}


rp++

原文地址:https://www.cnblogs.com/wzc521/p/11670746.html

时间: 2024-07-31 10:37:34

[CSP-S模拟测试]:简单的期望(DP)的相关文章

[CSP-S模拟测试]:走路(期望DP+分治消元)

题目传送门(内部题100) 输入格式 第一行两个整数$n,m$,接下来$m$行每行两个整数$u,v$表示一条$u$连向$v$的边.不保证没有重边和自环. 输出格式 $n-1$行每行一个整数,第$i$行表示$k=i+1$时的答案.对$998244353$取模. 样例 样例输入: 3 61 11 22 12 21 33 1 样例输出: 45 数据范围与提示 数据范围: 对于$25\%$的数据,$n\leqslant 50$. 对于另外$20\%$的数据,前$m-1$条边满足$u<v$. 对于另外$1

「10.13晚」简单的序列(DP)&#183;简单的期望(DP)&#183;简单的操作(二分图+最短路)

A. 简单的序列 一道$DP$题,容易想到卡特兰数 考虑$n-m$的范围很小,显然我们可以将他们拼起来, 怎么拼???? 然后我们可以枚举在$s$左侧放了多少个括号 假如我们将左括号看成$+1$,右括号看成$-1$,两边保证前缀大于$0$,且后缀小于$0$, 然后注意给出的$s$序列化简之后的情况,于是就愉快的获得$100$的好成绩 我会告诉你我$T1$打了快两个小时才$A$掉吗? B. 简单的期望 神仙DP. 考场完全没想到,事实是因为根本没想.... 考虑分解的二的个数,其实就是该数在二进制

[CSP-S模拟测试]:优化(贪心+DP)

题目描述 $visit\text{_}world$发现有下优化问题可以用很平凡的技巧解决,所以他给你分享了这样一道题:现在有长度为$N$的整数序列$\{ a_i\}$,你需要从中选出$K$个不想叫的连续子区间(可以存在元素不被选),从左到右记它们的和为$s_1,s_2,...,s_k$,我们的优化目标是最大化下述和式:$$\sum \limits_{i=1}^{k-1}|s_i-s_{i+1}|$$你只需要输出这个最大的和即可. 输入格式 第一行两个整数$N,K$,意义如上.接下来一行$N$个整

[CSP-S模拟测试]:Market(背包DP)

题目描述 在比特镇一共有$n$家商店,编号依次为$1$到$n$.每家商店只会卖一种物品,其中第$i$家商店的物品单价为$c_i$,价值为$v_i$,且该商店开张的时间为$t_i$. $Byteasar$计划进行$m$次购物,其中第$i$次购物的时间为$T_i$,预算为$M_i$.每次购物的时候,$Byteasar$会在每家商店购买最多一件物品,当然他也可以选择什么都不买.如果购物的时间早于商店开张的时间,那么显然他无法在这家商店进行购物. 现在$Byteasar$想知道,对于每个计划,他最多能购

[CSP-S模拟测试]:Seat(概率DP+数学)

题目描述 有$n+2$个座位等距地排成一排,从左到右编号为$0$至$n+1$.最开始时$0$号以及$n+1$号座位上已经坐了一个小$G$,接下来会有$n$个小$G$依次找一个空座位坐下.由于小$G$们坐得太近就容易互相搏弈,每个小$G$会找一个当前离最近的小$G$距离最远的座位坐下.如果有多个备选的座位,这个小$G$会等概率选择其中一个.给出$n$,求第$i$个坐下的小$G$坐在$j$号座位的概率,对$P$取模.具体来说,如果答案化为最简分数可以表示为$\frac{a}{b}$,你需要输出$a\

[CSP-S模拟测试]:Park(树上DP)

题目描述 公园里有$n$个雕像,有$n-1$条道路分别连接其中两个雕像,任意两个雕像可以直接或间接相连.现在每个景点$i$聚集着$P_i$只鸽子,旅行家手里有$v$数量的面包屑. 一旦旅行家在雕像$i$撒下$1$单位面包屑,那么相邻的雕像的鸽子就都会飞到雕像$i$来觅食. 时间线是这样的:首先,旅行家到达雕像$i$并与$P_i$鸽子会面.然后,他放下$1$单位面包屑.他离开雕像.在旅行家到达下一座雕像之前,来自相邻雕像的鸽子移动到雕像$i$(所以这些鸽子不计入他遇到的鸽子数).注意旅行家每到一达

[CSP-S模拟测试]:简单的括号序列(组合数)

题目传送门(内部题82) 输入格式 一行一个字符串$ss$,保证$ss$中只包含$'('$和$')'$. 输出格式 一行一个整数,表示满足要求的子序列数对$10^9+7$的结果. 样例 样例输入1: )(()() 样例输出1: 6 样例输入2: ()()() 样例输出2: 7 样例输入3: ))) 样例输出3: 0 数据范围与提示 样例解释: 第一组样例中,有以下几种子序列满足条件(字符串下标从$1$计数): 删除$1,5$位置的字符,得到$(())$ 删除$1,2,3,4$位置的字符,得到$(

[CSP-S模拟测试]:军训队列(DP+乱搞)

题目描述 有$n$名学生参加军训,军训的一大重要内容就是走队列,而一个队列的不规整程度是该队中最高的学生的身高与最矮的学生的身高差值的平方.现在要将$n$名参加军训的学生重新分成$k$个队列,每个队列的人数不限,请求出所有队列的不规整程度之和的最小值. 输入格式 第一行两个整数$n,k$,表示学生人数和队列数.第二行$n$个实数,表示每名学生的身高.身高范围在$140\sim 200cm$之间,保留两位小数. 输出格式 一个实数表示答案,保留$2$位小数. 样例 样例输入1: 3 2170.00

[CSP-S模拟测试]:简单的区间(分治)

题目描述 给定一个长度为$n$的序列$a$以及常数$k$,序列从$1$开始编号.记$$f(l,t)=\sum \limits_{i=l}^ra_i-\max \limits_{i=l}^r\{a_i\}$$求合法的正整数对$(l,r)$的数量,满足$1\leqslant l<r\leqslant n$,且$k|f(l,r)$. 输入格式 第一行两个正整数$n$和$k$. 第二行包含$n$个正整数,第$i$个正整数表示$a_i$. 输出格式 一行一个正整数,表示答案. 样例 样例输入1: 4 3