BZOJ 3652大新闻 数位dp+期望概率dp

Posted TS_Hugh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 3652大新闻 数位dp+期望概率dp相关的知识,希望对你有一定的参考价值。

并不难,只是和期望概率dp结合了一下.
稍作推断就可以发现加密与不加密是两个互相独立的问题,这个时候我们分开算就好了.
对于加密,我们按位统计和就好了;对于不加密,我们先假设所有数都找到了他能找到的最好的匹配(就是异或后为二进制最高位与n-1相等的最大数)并且算出其异或后的总和,然后我们按位贪心,带着所有的数(一开始我们假设所有的数是小于等于二进制最高位与n-1相等的最大数的所有数)从高位走向低位,每走一步,如果这一位是0,就会导致一半的数在这一位不能是1,减去这一半的数在这一位上的贡献,如果这一位是1,就意味着一半的数往后一定会全部是1,我们把这一半数从我们带着的数中减去,另一半待定(留下).
这样思路清晰,实现简易,只是一定注意贡献不要统计错.

#include <cstdio>
typedef double db;
typedef long long LL;
LL f,bin[61],n,temp;
db ans1,ans2,p;
int digit[61],bit,i,j;
int main(){
  scanf("%lld%lf",&n,&p),bin[0]=1,temp=--n;//我的代码需要的是n-1
  while(temp)digit[++bit]=temp&1,temp>>=1,bin[bit]=bin[bit-1]<<1;
  for(i=bit;i>0;--i){
    f=temp;
    if(digit[i])f+=(n&(bin[i-1]-1))+1,temp+=bin[i-2];//这一位如果是1的话,对后面都有贡献,所以要累加temp
    ans1+=(db)f*(n-f+1)*2.*bin[i-1];
  }
  ans1=ans1/(n+1.)/(n+1.);
  ans2=(db)(n+1.)*(bin[bit]-1);
  temp=bin[bit]; 
  for(i=bit;i>0;--i)
    if(digit[i]&1)temp>>=1;
    else ans2-=(db)(temp>>1)*bin[i-1];
  ans2/=(n+1.);
  printf("%.6f\\n",ans1*(1.-p)+ans2*p);
  return 0;  
}

 

以上是关于BZOJ 3652大新闻 数位dp+期望概率dp的主要内容,如果未能解决你的问题,请参考以下文章

数位dp——hud3652

HDU 3652 数位dp

hdu3652 数位dp记忆化搜索

HDU-3652(数位dp)

hdu-3652 B-number 数位DP

HDU 3652 B-number 数位DP