Description
有\(p\)的概率没有被加密。求期望。
如果没有被加密那么求\([0,n)\)随机选择一个数\(x\)然后再选择小于\(n\)的\(y\)使\(x\)^\(y\)最大的异或和的期望。
如果被加密那么求随机选择\([0,n)\)两个数\(x,y\),求异或和的期望。
Solution
数位DP.
强行期望?
被加密了那就很简单了,跟SDOI2016一样。
如果没被加密,我做的方法比较蠢...做法还是一样,状态表示也是一样...
分类讨论统计出来个数,然后统计答案,为了方便我算的是小于等于\(n\)的...
Code
/**************************************************************
Problem: 3652
User: BeiYu
Language: C++
Result: Accepted
Time:0 ms
Memory:1296 kb
****************************************************************/
#include <bits/stdc++.h>
using namespace std;
#define B(a) cout<<(#a)<<"="<<a<<" "
typedef long long LL;
typedef long double LD;
const int N = 70;
LL n;
double p,ans,tmp;
double f[N][2][2];
double g[N][2][2];
double pw[N];
int main() {
cin>>n>>p;
pw[0]=1;for(int i=1;i<N;i++) pw[i]=pw[i-1]*2;
g[63][1][1]=1;
for(int i=62;~i;i--) {
int a=(n>>i)&1;
for(int xx=0;xx<2;xx++) for(int yy=0;yy<2;yy++) {
int zz=xx^yy;
for(int aa=0;aa<2;aa++) for(int bb=0;bb<2;bb++) {
if(aa && xx>a) continue;
if(bb && yy>a) continue;
int na=aa?(xx==a):0,nb=bb?(yy==a):0;
f[i][na][nb]+=f[i+1][aa][bb]+zz*pw[i]*g[i+1][aa][bb];
g[i][na][nb]+=g[i+1][aa][bb];
}
}
}
ans=(1-p)*f[0][0][0]/n/n;
memset(f,0,sizeof(f)),memset(g,0,sizeof(g));
n--;
int l=63;for(;pw[l]>n;l--);
g[l][0][1]=pw[l],g[l][1][0]=n-pw[l]+1;
f[l][0][1]=pw[l]*g[l][0][1],f[l][1][0]=pw[l]*g[l][1][0];
tmp+=f[l][0][1]+f[l][1][0];
for(int i=l-1;i>=0;i--) {
int a=(n>>i)&1,b=(n>>i)&1;
for(int xx=0;xx<2;xx++) {
for(int aa=0;aa<2;aa++) for(int bb=0;bb<2;bb++) if(g[i+1][aa][bb]) {
if(aa && xx>a) continue;
int yy=xx^1;
if(bb && yy>b) yy^=1;
int zz=xx^yy;
int na=aa?xx==a:0,nb=bb?yy==b:0;
double gg=0;
if(aa) {
if(a) {
if(na) g[i][na][nb]+=g[i+1][aa][bb]-pw[i-1],gg=g[i+1][aa][bb]-pw[i-1];
else g[i][na][nb]+=pw[i-1],gg=pw[i-1];
} else {
if(na) g[i][na][nb]+=g[i+1][aa][bb],gg=g[i+1][aa][bb];
}
} else {
g[i][na][nb]+=g[i+1][aa][bb]/2,gg=g[i+1][aa][bb]/2;
}
// B(i),B(aa),B(bb),B(xx),B(yy),B(na),B(nb)<<endl;
// B(zz),B(gg)<<endl;
f[i][na][nb]+=zz*pw[i]*gg;
tmp+=(zz*pw[i]*gg);
}
}
}
ans=(ans+p*tmp/(n+1));
printf("%.11lf\n",ans);
return 0;
}