ch3801 Rainbow的信号
关于计算期望的题,具体解法书上已经说的很清楚了
有一个值得注意的事项,就是我们枚举每一位的时候,应该选择从最低位往最高位枚举
否则最终答案会出错,主要是因为浮点数计算出的问题,因为懒得测试,但根据数值书上学的可能原因应该是计算过程后期所加的数很小,两者数量级相差太大,导致小数被吃掉
因为测试数据最终答案相差不大,其他原因不知道,以后要注意
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<string> #include<queue> #include<map> #include<set> #include<stack> #include<list> #include<ctime> #include<ctype.h> #include<stdlib.h> #include<bitset> #include<algorithm> #include<assert.h> #include<numeric> //accumulate #define endl "\n" #define fi first #define se second #define FOR(i,s,t) for(int i=(s);i<=(t);++i) #define mem(a,b) memset(a,b,sizeof(a)) #define rush() int MYTESENUM;scanf("%lld",&MYTESENUM);while(MYTESENUM--) #define debug(x) printf("%d\n",x) using namespace std; const int maxn=100000+5; int n; int a[maxn],b[maxn],last[2]; double ans_xor,ans_or,ans_and; int c1,c2; inline void solve(int k) { mem(last,0); c1=c2=0; for(int i=1;i<=n;i++) { b[i]=a[i]>>k&1; if(b[i]) { ans_xor+=1.0*(1<<k)/n/n; ans_and+=1.0*(1<<k)/n/n; ans_or+=1.0*(1<<k)/n/n; } } for(int i=1;i<=n;i++) { if(b[i]) { ans_and+=2.0*(1<<k)/n/n*(i-last[0]-1); ans_or+=2.0*(1<<k)/n/n*(i-1); } else { ans_or+=2.0*(1<<k)/n/n*last[1]; } ans_xor+=2.0*(1<<k)/n/n*(b[i]?c1:c2); c1++; if(b[i]) swap(c1,c2); last[b[i]]=i; } } int main() { cin.tie(0); cout.tie(0); //ios_base::sync_with_stdio(0); //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } for(int i=0;i<=30;i++) { solve(i); } printf("%.3f %.3f %.3f",ans_xor,ans_and,ans_or); }
浙公网安备 33010602011771号