解题思路
这道题的解法还是有点颠覆了我,不符合我正常阅题逻辑。。
讲解》》大新闻
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<iomanip>
#include<cstring>
#include<cmath>
#include<map>
#include<queue>
#include<set>
#define ll long long
#define ldb long double
using namespace std;
ll n,t;
ldb ans,p;
ldb get_mi(ll x){
ll xx=1;
while(xx<=x)
xx<<=1;
return xx>>1;
}
ldb sum(ll x,ll y){
return 1.0*(x+y)*(y-x+1)/2;
}
ldb work1(ll x){
if(x<=1)return 0;
ll xx=get_mi(x);
return sum(0,xx-1)*xx+sum(xx,xx+xx-1)*(x-xx)*2+work1(x-xx);
}
ldb work2(ll x,ll y,ll u){
if(!x||!y)
return 0;
if(y==1)return u;
ll xx=get_mi(y-1);
if(x>xx)
return (1.0*u+xx*2-1)*(1.0*y-xx)+work2(x-xx,xx,u+xx);
else return 1.0*xx*xx+work2(x,xx,u)*2;
}
int main(){
scanf("%lld%Lf",&n,&p);
ldb ans=(1-p)*work1(n)/n/n+p*work2(n,n,0)/n;
while(ans/10>=1)
{
ans/=10;
t++;
}
while(ans<1&&ans)
{
ans*=10;
t--;
}
printf("%.6Lf %lld",ans,t);
}