zoukankan      html  css  js  c++  java
  • [CSP-S模拟测试]:简单的期望(DP)

    题目描述

    从前有个变量$x$,它的初始值已给出。
    你会依次执行$n$次操作,每次操作有$p\%$的概率令$x=x imes 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\%$的数据,$nleqslant 20$;
    对于$30\%$的数据,$nleqslant 50$;
    对于$50\%$的数据,$nleqslant 100$;
    对于$100\%$的数据,$xleqslant 10^9,nleqslant 200,0leqslant pleqslant 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++

  • 相关阅读:
    动态规划Dynamic Programming: Rod-Cutting Problem
    递归详解,全排列问题
    获取网站根目录Url
    oracle中操作表和权限
    mongo简单封装
    dapper的简单封装
    反射做字段更新日志
    nopcommerce +autofac +owin +webapi
    批处理命令执行程序
    MSMQ的简单使用
  • 原文地址:https://www.cnblogs.com/wzc521/p/11670746.html
Copyright © 2011-2022 走看看