性質:一個數分解質因數後2的次數=二進制下末尾連續0的個數。ios
乘2比較好考慮,比較噁心的是+1。一個$k*2^0$的數+1後可能會出現不少狀況。可是k這個數表示不出來。spa
可是加的操做最多有200次,也就是說最多影響二進制下的後8位。根據上述性質,咱們把後8爲做爲狀態,統計機率。blog
可是隻有後8位狀態的的話仍是不可作,再加上第9位狀態以及與第九位相同的連續長度來考慮進位。ci
即f[i][j][s][k]表示i次操做後,後8位爲s,第九位爲k,有連續j位的機率。string
轉移少麻煩但仍是比較好想的。本題難度在於狀態定義。it
#include<iostream> #include<cstring> #include<cstdio> #include<bitset> #define int LL #define LL long long using namespace std; int x,n,p; double gl1,gl2; double f[210][255][1<<10][2]; int cnt[1<<10]; signed main() { // freopen("in.txt","r",stdin); // freopen("1.out","w",stdout); cin>>x>>n>>p; gl1=p/100.0,gl2=(100-p)/100.0; int num=0; for(int j=0;(((1<<j)&x)==0);j++)num++; f[0][num>8?num-8:1][x&((1<<8)-1)][(bool)(x&(1<<8))]=1; // cout<<(num>8?num-8:1)<<" "<<(x&((1<<8)-1))<<" "<<(x&(1<<8))<<endl; for(int i=0;i<n;i++) for(int j=1;j<=250;j++) for(int s=0;s<(1<<8);s++) { if(s!=(1<<8)-1)f[i+1][j][s+1][0]+=f[i][j][s][0]*gl2; else f[i+1][1][0][1] +=f[i][j][s][0]*gl2; if(s!=(1<<8)-1)f[i+1][j][s+1][1]+=f[i][j][s][1]*gl2; else f[i+1][j][0][0] +=f[i][j][s][1]*gl2; bool maxn=s&(1<<7); f[i+1][maxn==0?j+1:1][(s<<1)&((1<<8)-1)][maxn]+=f[i][j][s][0]*gl1; f[i+1][maxn==1?j+1:1][(s<<1)&((1<<8)-1)][maxn]+=f[i][j][s][1]*gl1; } /* for(int i=0;i<n;i++) for(int j=1;j<=10;j++) for(int s=0;s<(1<<8);s++) cout<<f[i][j][s][0]<<" "<<f[i][j][s][1]<<endl*/ for(int i=0;i<(1<<8);i++) for(int j=0;j<=8&&(((1<<j)&i)==0);j++)cnt[i]++; double ans=0; for(int i=1;i<(1<<8);i++) for(int j=1;j<=250;j++) ans+=(f[n][j][i][0]+f[n][j][i][1])*cnt[i]; for(int j=1;j<=250;j++)ans+=f[n][j][0][0]*(j+8)+f[n][j][0][1]*8; printf("%0.10lf\n",ans); }