标签:turn 变量 printf oid 复杂度 lag 计算 操作 using
从前有个变量$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++
标签:turn 变量 printf oid 复杂度 lag 计算 操作 using
原文地址:https://www.cnblogs.com/wzc521/p/11670746.html