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++

  • 相关阅读:
    Luogu-P2295 MICE
    Luogu-P2627 修剪草坪
    Loj-10176-最大连续和
    Luogu-P1886 滑动窗口
    Luogu-P3807 【模板】卢卡斯定理
    Luogu-P1879 [USACO06NOV]玉米田Corn Fields
    Luogu-P1896 [SCOI2005]互不侵犯
    Loj-SGU 223-国王
    Luogu-P2657 [SCOI2009]windy数
    素数
  • 原文地址:https://www.cnblogs.com/wzc521/p/11670746.html
Copyright © 2011-2022 走看看