[CodeForces-441E]Valera and Number

题目大意:
  给你一个数x,进行k次操作:
  1.有p%的概率将x翻倍;
  2.有1-p%的概率将x加1。
  问最后二进制下x末尾0个数的期望。

思路:
  动态规划。
  由于k只到200,所以每次修改只与最后8位有关。
  f[i][x][y][z]表示操作次数为i时,末尾8为表示的数字为x,第9位为y,第9位及以上和第9位数字连续相同的长度。
  对于两种情况分别转移,注意特判超过8位的进位。
  最后计算期望的时候,可以枚举第一维为k的所有状态,然后通过状态可以直接计算出末尾0的数量,乘上概率即可。

 1 #include<cstdio>
 2 #include<cctype>
 3 inline int getint() {
 4     register char ch;
 5     while(!isdigit(ch=getchar()));
 6     register int x=ch^'0';
 7     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
 8     return x;
 9 }
10 const int K=201;
11 double f[K][256][2][230];//[処理回数][末尾8bit][9bit目の値][9bit目の値が上にいくつ連続するか]
12 int main() {
13     int x=getint(),k=getint();
14     double p=getint()/100.0;
15     //初始状态
16     int cnt=0,tmp=x>>8;
17     while(tmp&&((tmp&1)==((x>>8)&1))) {
18         tmp>>=1;
19         cnt++;
20     }
21     f[0][x&255][(x>>8)&1][cnt]=1;
22     for(register int i=0;i<k;i++) {
23         for(register int x=0;x<=255;x++) {
24             for(register int y=0;y<2;y++) {
25                 for(register int z=0;z<230;z++) {
26                     /*times 2*/
27                     f[i+1][(x<<1)&255][(x>>7)&1][(((x>>7)&1)^y)?1:(z+1)]+=f[i][x][y][z]*p;
28                     /*plus 1*/
29                     if(x==255) {//特殊情况:考虑最后八位存不下而进位的情况 
30                         if(y) {//如果第九位是1,则相当于前面那么多1都变成0 
31                             f[i+1][0][0][z]+=f[i][x][y][z]*(1-p);
32                         } else {//如果第九位是0,则相当于把这个0变成1 
33                             f[i+1][0][1][1]+=f[i][x][y][z]*(1-p);//这里把9位以后的1算作多少都没关系,因为反正最后统计的是0 
34                         }
35                     } else {
36                         f[i+1][x+1][y][z]+=f[i][x][y][z]*(1-p);
37                     }
38                 }
39             }
40         }
41     }
42     //计算期望
43     double ans=0;
44     for(register int x=0;x<=255;x++) {
45         for(register int y=0;y<2;y++) {
46             for(register int z=0;z<230;z++) {
47                 int cnt=0,tmp=x;
48                 while(cnt<8&&!(tmp&1)) {
49                     cnt++;
50                     tmp>>=1;
51                 }
52                 if(!y&&cnt==8) cnt+=z;
53                 ans+=f[k][x][y][z]*cnt;
54             }
55         }
56     }
57     printf("%.13f
",ans);
58     return 0;
59 }
原文地址:https://www.cnblogs.com/skylee03/p/7682246.html