【GDKOI2017模拟1.12】与运算
2017-01-16 21:59
141 查看
Description
给出一个序列,Fi为前i项进行and运算之后的值。求这个序列的一个排列,使得∑Fi最大。输出这个最大值。
n<=10^6
Solution
首先考虑F数组,显然是单调不升的。那么我们考虑Dp,Dp i表示F数组目前最后一位为i的最大和。注意可以不放满。
那么我们枚举一个数转移,复杂度是O(N^2)的。
转移的话我们可以预处理cnt[i]表示有多少个数and i等于i的。
这个东西可以用经典分治求出来,把二进制每一位分成0和1,把1的答案加到0上。
然后转移就显然了。
然后我们发现如果我们把转移看做很多次减去一个2的幂,那么每一次我们只需要把i的二进制减去一个1就好了。
每次转移可以拆成很多次转移嘛~
Code
#include <cstdio> #include <cstring> #include <algorithm> #define fo(i,a,b) for(int i=a;i<=b;i++) #define fd(i,a,b) for(int i=a;i>=b;i--) using namespace std; typedef long long ll; const int N=1.5*1e6+5,D=20; int cnt ,mi[D+5],n,x; ll f ,ans; void solve(int l,int r) { if (l==r) return; int mid=(l+r)/2; solve(l,mid);solve(mid+1,r); fo(i,mid+1,r) cnt[i-mid+l-1]+=cnt[i]; } int main() { freopen("and.in","r",stdin); freopen("and.out","w",stdout); scanf("%d",&n); fo(i,1,n) scanf("%d",&x),cnt[x]++; mi[0]=1; fo(i,1,D) mi[i]=mi[i-1]*2; solve(0,mi[D]-1); f[mi[D]-1]=cnt[mi[D]-1]*(mi[D]-1); fd(i,mi[D]-1,0) { fo(j,0,D) if (i&mi[j]) { x=i-mi[j]; f[x]=max(f[x],f[i]+(ll)x*(cnt[x]-cnt[i])); } ans=max(ans,f[i]); } printf("%lld\n",ans); }
相关文章推荐
- JZOJ 4937 【GDKOI2017模拟1.12】与运算
- JZOJ 4937【GDKOI2017模拟1.12】与运算
- 【JZOJ4937】【GDKOI2017模拟1.12】与运算
- DSP中浮点转定点运算--定点数模拟浮点数运算及常见的策略
- Just a Numble模拟除法的运算
- 模拟二进制运算
- FZU - 1061 矩阵连乘 【模拟运算--矩阵连乘】
- 模拟电子技术33 50-------- 运算放大器 差模电路
- <数据结构学习与实验指导>3-3银行业务队列模拟/3-4一元多项式的乘法与加法运算
- JZOJ 4936 【NOIP2017GDKOI模拟1.12】c
- c++ 模拟浮点数运算
- Book 【GDKOI2017模拟1.21】
- 模拟复数及其运算
- 栈模拟 四则运算 (没写完)
- 矩阵的运算的乘法次数(栈的模拟应用)
- 智商200以上才能通关的小游戏“智慧翻转”的模拟运算程序
- A除以B (模拟竖式除法运算)
- 模拟电子技术34 51-------- 运算放大器 差模电路 续
- 模拟复数及其运算
- 【GDKOI2017模拟1.21】Rhyme