XDOJ-1006-亮亮破解密码(数列中所有区间位操作值之和)
2017-04-12 18:28
791 查看
题目链接:XDOJ-1006-亮亮破解密码
考虑将每个数化为二进制,然后对二进制的每一位进行操作。
对于异或,处理出所有的后缀异或值,然后从后往前更新,维护其中值为1的数量和值为0的数量即可。
对于与,处理出所有连续1的数量,只有连续1与值才能为1
对于或,处理出所有连续0的数量。
考虑将每个数化为二进制,然后对二进制的每一位进行操作。
对于异或,处理出所有的后缀异或值,然后从后往前更新,维护其中值为1的数量和值为0的数量即可。
对于与,处理出所有连续1的数量,只有连续1与值才能为1
对于或,处理出所有连续0的数量。
#include<bits/stdc++.h> using namespace std; const int maxn=1e5+7; typedef long long ll; double ans[3]; int n; bool a[maxn][30]; int main() { while(~scanf("%d",&n)) { int t; for(int i=0;i<n;i++) { scanf("%d",&t); for(int j=0;j<30;j++) a[i][j]=(t>>j)&1; } int pre; int c[2]; ans[0]=ans[1]=ans[2]=0; for(int j=0;j<30;j++) { pre=0; c[0]=c[1]=0; ll res=0; for(int i=n-1;i>=0;i--) { pre^=a[i][j]; ++c[pre]; } for(int i=n-1;i>=0;i--) { --c[a[i][j]]; res+=c[1]*2+a[i][j]; if(a[i][j]) swap(c[0],c[1]); } ans[0]+=res*1.0/n/n*(1<<j); } for(int j=0;j<30;j++) { ll cnt=0,res=0; for(int i=0;i<=n;i++) { if(a[i][j]&&i!=n) cnt++; else if(cnt) { res+=cnt*cnt; cnt=0; } } ans[1]+=res*1.0/n/n*(1<<j); } for(int j=0;j<30;j++) { ll cnt=0,res=1LL*n*n; for(int i=0;i<=n;i++) { if(!a[i][j]&&i!=n) cnt++; else if(cnt) { res-=cnt*cnt; cnt=0; } } ans[2]+=res*1.0/n/n*(1<<j); } printf("%.3f %.3f %.3f\n",ans[0],ans[1],ans[2]); } return 0; }
相关文章推荐
- 所有的密码都是可破解的
- 破解电脑密码的所有妙方,请收藏保存
- 破解Access(*.mdb)目前所有版本的密码
- XDOJ1109 - 破解密码
- 破解Access(*.mdb)目前所有版本的密码
- [C#] 10进制转62进制,实现穷举指定位数的所有密码组合(暴力破解)
- 破解Access(*.mdb)目前所有版本的密码
- 30秒破解所有密码
- 30秒破解所有密码
- 电脑所有密码破解总结
- 30妙破解所有密码
- 中国电信某接口可破解某省所有用户服务密码姓名信息并可通过服务密码免费兑换礼品变现
- 一个可能破解所有公钥密码的方法
- 10进制转62进制,实现穷举指定位数的所有密码组合(暴力破解)
- 30秒破解所有密码(非常适合我们)
- 招教你破解所有电脑开机密码
- 破解windows密码,破解sam文件(syskey加密)
- 1138:破解简单密码
- 破解asp木马密码
- linux redhat Centos debian 破解root 密码 “Give root password for maintenance”