简单的期望「状压dp」

题意

题解

dp定义真的神,

直接的想法是$f[x][maxn]$为第$x$个操作,状态$maxn$,$maxn$1<<200,好像没有暴力分高

实际上我们可以这样定义$f[x][maxn][len][0/1]$表示后八位$maxn$,第九位0\1,第九位之后连续长度为$j$概率

为什么这样定义

实际上质因数分解后2的次数就是后面0的个数

+1会破坏已有的0,操作数最多只有200个全部+1后八位已经足够

最多只会影响到后九位一次

考虑一种极限情况

111111111111111

现在在最后一位加一会进位

1000000000000000,再怎么+1都不会再影响到九位之后了

 

 

转移比较简单具体看代码

代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 ll x,n,m,xx,opt,maxn,cnt;
 5 double p,ans=0;
 6 double f[210][288][310][2];
 7 ll cal(ll now){
 8     ll cnt=0;
 9     while(now%2==0) cnt++,now/=2;
10     return cnt;
11 }
12 int main(){
13 //    freopen("cnm.xlsx","w",stdout);
14     scanf("%lld%lld%lf",&x,&n,&p);
15     p/=100;
16     xx=x;
17     xx>>=8;
18     opt=xx&1;
19     maxn=(1<<8)-1;
20     for(;xx&&((xx&1)==opt);xx>>=1)
21         cnt++;
22     if(cnt==0) cnt++;//
23     m=cnt+n;
24     f[0][x&maxn][cnt][opt]=1;
25 //    printf("%lld\n",m);
26     for(ll i=1;i<=n;i++)
27         for(ll pre=0;pre<=maxn;pre++)
28             for(ll j=1;j<=m;j++)
29                 for(ll t=0;t<=1;t++)
30                 if(f[i-1][pre][j][t]){        
31                     ll now,tt,jj;
32                     now=pre+1;
33                     if(now==(1<<8)){
34                         now=0;tt=t^1;
35                         if(t==1) jj=j;
36                         else jj=1;
37                     }
38                     else jj=j,tt=t;
39                     f[i][now][jj][tt]+=f[i-1][pre][j][t]*(1-p);
40                     now=pre<<1;
41                     if(((now>>8)&1)==t) tt=t,jj=j+1;    
42                     else tt=t^1,jj=1;
43                     now=now&maxn;
44                     f[i][now][jj][tt]+=f[i-1][pre][j][t]*p;
45                 }
46     for(ll now=1;now<=maxn;now++)//
47         for(ll j=1;j<=m;j++)
48             for(ll t=0;t<=1;t++)
49                 if(f[n][now][j][t])
50                 ans+=f[n][now][j][t]*cal(now);
51                 //,printf("f[%lld][%lld][%lld][%lld]=%lf\n",n,now,j,t,f[n][now][j][t]);
52 //    printf("%.13lf\n",ans);
53     for(ll j=1;j<=m;j++){
54         ans+=f[n][0][j][0]*(j+8)+f[n][0][j][1]*8;
55 //        printf("f[%lld][0][%lld][0]=%lf f[%lld][0][%lld][1]=%lf\n",n,j,f[n][0][j][0],n,j,f[n][0][j][1]);
56     }
57     printf("%.13lf\n",ans);
58 }
View Code

 

posted @ 2019-10-22 15:07  znsbc  阅读(167)  评论(0编辑  收藏  举报