(似乎漏了一个数据范围,cf上的题面中还有$\sum L\le 3\cdot 10^{5}$)

考虑$a_{i}=2^{k_{i}}$时(不妨$k_{1}\ge k_{2}\ge ...\ge k_{n}$),记$\sum_{i=1}^{n}b_{i}$的最高位为$L_{b}$,则有$L_{b}=\max_{i=1}^{n}(k_{i}+i-1)$

证明:大于等于$2^{k_{i}}$的$b_{i}$至少要$i$个,因此该值即为下限;取$b_{i}=2^{L_{b}-i+1}\ge 2^{k_{i}}$,因此一定可行

利用上面的这个结论,我们开始考虑正解

如果令$k_{i}$表示$a_{i}$最高的二进制位,那么$2^{k_{i}}\le a_{i}<2^{k_{i}+1}$,取$a'_{i}=2^{k_{i}+1}$,设此时$\sum_{i=1}^{n}b_{i}$的最高为$L_{b}+1$,$a_{i}$减小$b_{i}$不增,因此答案中$\sum_{i=1}^{n}b_{i}$的最高位不超过$L_{b}+1$

令$t=\min_{k_{i}+i=L_{b}}i$,考虑答案($\sum_{i=1}^{n}b_{i}$)的第$[k_{t},L_{b}+1]$位(共$t+1$位),必然存在$t$位为1(每一个1最多消除一个$a_{i}$,而存在$t$个$a_{i}$最高位大于等于$k_{t}$)

又因为$\forall 1\le i<t,k_{i}+i-1<L_{b}$,即通过这$t$位1中最高的$t-1$位(即使是$L_{b}-i+1$)一定可以,同时也必然会删除$a_{1},a_{2},...,a_{t-1}$

由于$[k_{t},L_{b}+1]$中第$t$个1(从高到低)必然是$k_{t}+1$位或第$k_{t}$位(也有可能都选),判定当第$k_{t}+1$位为0时能否删除$a_{t},a_{t+1},...,a_{n}$,对结果分类讨论:

1.若可以,即最低位可以为$k_{t}$,必然贪心选择令第$[k_{t},L_{b}]$位为1并剩下$a_{t}-2^{k_{t}}$

2.若不可以,则第$[k_{t}+1,L_{b}+1]$位都必须填1,之后将$a_{1},a_{2},..,a_{t}$都删除即可

考虑如何判定,可以再次调用本过程(递归),即在判定过程中顺便求出最小解(若有解,否则返回无解),因此对于第1种情况直接就可以退出,第2种仍要递归下去

时间复杂度很玄学,递归次数大概是$o(L)$的

对于每一次内部,用线段树来维护区间最大值,具体方法如下:

1.对于$i$可以通过插入/删除一个数时,对之后的位置+1或-1来实现

2.对于每一个$a_{i}$,剩余的一定是二进制下的一个后缀,那么将所有数每一个后缀(其实也只需要那一位上有1,否则跟上一个后缀相同)放在一起基数排序,至多为$o(\sum L)$个数

3.对于每一个$a_{i}$,要维护下一个1的位置(预处理);对于线段树上,维护区间最大值,以及查询第一个最大值并将小于等于其的位置暴力插入,支持单点插入或删除

这样的复杂度再多一个log,总复杂度即为$o((\sum L)\log \sum L)$

  1. 1 #include<bits/stdc++.h>
  2. 2 using namespace std;
  3. 3 #define N 300005
  4. 4 #define oo 0x3f3f3f3f
  5. 5 #define L (k<<1)
  6. 6 #define R (L+1)
  7. 7 #define mid (l+r>>1)
  8. 8 vector<int>v[N];
  9. 9 int n,m,la,rk[N],bit[N],nex[N],top[N],ans[N],f[N<<2],tag[N<<2];
  10. 10 char s[N];
  11. 11 bool cmp(int x,int y){
  12. 12 return rk[x]>rk[y];
  13. 13 }
  14. 14 void upd(int k,int x){
  15. 15 tag[k]+=x;
  16. 16 f[k]+=x;
  17. 17 }
  18. 18 void down(int k){
  19. 19 upd(L,tag[k]);
  20. 20 upd(R,tag[k]);
  21. 21 tag[k]=0;
  22. 22 }
  23. 23 void build(int k,int l,int r){
  24. 24 if (l==r){
  25. 25 f[k]=bit[l]-oo;
  26. 26 return;
  27. 27 }
  28. 28 build(L,l,mid);
  29. 29 build(R,mid+1,r);
  30. 30 f[k]=max(f[L],f[R]);
  31. 31 }
  32. 32 void update(int k,int l,int r,int x,int y,int z){
  33. 33 if ((l>y)||(x>r))return;
  34. 34 if ((x<=l)&&(r<=y)){
  35. 35 upd(k,z);
  36. 36 return;
  37. 37 }
  38. 38 down(k);
  39. 39 update(L,l,mid,x,y,z);
  40. 40 update(R,mid+1,r,x,y,z);
  41. 41 f[k]=max(f[L],f[R]);
  42. 42 }
  43. 43 void query(int k,int l,int r,int x,vector<int>&v){
  44. 44 if (f[k]<0)return;
  45. 45 if (l==r){
  46. 46 v.push_back(l);
  47. 47 return;
  48. 48 }
  49. 49 down(k);
  50. 50 query(L,l,mid,x,v);
  51. 51 if (f[L]!=x)query(R,mid+1,r,x,v);
  52. 52 }
  53. 53 void add(int k){
  54. 54 update(1,1,m,k,k,oo);
  55. 55 if (k<m)update(1,1,m,k+1,m,1);
  56. 56 }
  57. 57 void del(int k){
  58. 58 update(1,1,m,k,k,-oo);
  59. 59 if (k<m)update(1,1,m,k+1,m,-1);
  60. 60 }
  61. 61 bool dfs(int mx){
  62. 62 int lb=f[1];
  63. 63 if (lb<0)return 1;
  64. 64 if (lb>mx)return 0;
  65. 65 vector<int>v;
  66. 66 query(1,1,m,lb,v);
  67. 67 for(int i=0;i<v.size();i++)del(v[i]);
  68. 68 int t=v.back();
  69. 69 if (nex[t])add(nex[t]);
  70. 70 if (dfs(bit[t]-1)){
  71. 71 for(int i=bit[t];i<=lb;i++)ans[i]=1;
  72. 72 return 1;
  73. 73 }
  74. 74 if (nex[t])del(nex[t]);
  75. 75 if ((lb+1<=mx)&&(dfs(bit[t]))){
  76. 76 for(int i=bit[t];i<=lb;i++)ans[i+1]=1;
  77. 77 return 1;
  78. 78 }
  79. 79 for(int i=0;i<v.size();i++)add(v[i]);
  80. 80 return 0;
  81. 81 }
  82. 82 int main(){
  83. 83 scanf("%d",&n);
  84. 84 for(int i=1;i<=n;i++){
  85. 85 scanf("%s",s);
  86. 86 int l=strlen(s);
  87. 87 la=max(la,l);
  88. 88 for(int j=0;j<l;j++)
  89. 89 if (s[j]=='1'){
  90. 90 m++;
  91. 91 v[l-j-1].push_back(i);
  92. 92 }
  93. 93 }
  94. 94 for(int i=1;i<=n;i++)rk[i]=m+1;
  95. 95 int mm=m;
  96. 96 for(int i=0;i<la;i++){
  97. 97 sort(v[i].begin(),v[i].end(),cmp);
  98. 98 for(int j=0;j<v[i].size();j++){
  99. 99 bit[mm]=i;
  100. 100 rk[v[i][j]]=mm;
  101. 101 nex[mm]=top[v[i][j]];
  102. 102 top[v[i][j]]=mm--;
  103. 103 }
  104. 104 }
  105. 105 build(1,1,m);
  106. 106 for(int i=1;i<=n;i++)add(top[i]);
  107. 107 dfs(oo);
  108. 108 bool flag=0;
  109. 109 for(int i=n+la;i>=0;i--)
  110. 110 if ((flag)||(ans[i])){
  111. 111 flag=1;
  112. 112 printf("%d",ans[i]);
  113. 113 }
  114. 114 }

[loj2850]无进位加法的更多相关文章

  1. [剑指Offer]65-不用加减乘除做加法

    题目 写一个函数,求两个整数之和,要求在函数体内不得使用+.-.*./四则运算符号. 题解 用位运算模拟加法的三步: 无进位加法:异或运算. 进位:与运算再左移一位. 直到进位为0结束. 代码 pub ...

  2. 【数学】XMU 1593 找数字

    题目链接: http://acm.xmu.edu.cn/JudgeOnline/problem.php?id=1593 题目大意: T组数据,n个数,只有一种出现q次,其余的出现p次.(1<=T ...

  3. 位运算-出现k次与出现一次

    题目:数组中arr只有一个数出现了1次,其他的数都出现了k次,请输出这个只出现了一次的数. 思路:这道题目要求使用位运算实现,如果采用数据结构Map就会简单很多.解此题前先了解不进位加法的思想,比如两 ...

  4. fpga加法进位链实现过程中的一个特点

    altera fpga 用quartus综合后会出现加法进位链一正一反的情况,所谓一正一反指的是假设某一级输入为a,b,进位值为c,则该级进位链逻辑应该为cout=ab+ac+bc,但实际为 cout ...

  5. 剑指offer编程题Java实现——面试题12相关题大数的加法、减法、乘法问题的实现

    用字符串或者数组表示大数是一种很简单有效的表示方式.在打印1到最大的n为数的问题上采用的是使用数组表示大数的方式.在相关题实现任意两个整数的加法.减法.乘法的实现中,采用字符串对大数进行表示,不过在具 ...

  6. LeetCode:位运算实现加法

    LeetCode:位运算实现加法 写在前面 位运算符 实现加法的思路 两个加数,比如5(101)和6(110),如何不用加法就能得出两者之和呢? 我们知道二进制计算中,如果使用异或将会产生无进位的两者 ...

  7. 51NOD 大数加法以及python写法

    练练 大数加法一般为小学生式的"竖式计算"要特别注意的是借位与进位的问题(先给看c++写法,我怕先看了python写法,会看不下去c++写法)这题还有要注意的是 1.同符号的话,直 ...

  8. 【剑指offer】65. 不用加减乘除做加法

    剑指 Offer 65. 不用加减乘除做加法 知识点:数学:位运算 题目描述 写一个函数,求两个整数之和,要求在函数体内不得使用 "+"."-"."* ...

  9. 【剑指Offer】不用加减乘除做加法 解题报告(Java)

    [剑指Offer]不用加减乘除做加法 解题报告(Java) 标签(空格分隔): 剑指Offer 题目地址:https://www.nowcoder.com/ta/coding-interviews 题 ...

随机推荐

  1. Firewalls文件配置防火墙

    1.源文件 /usr/lib/firewalld/services 2.文件配置 cat /etc/firewalld/zones/public.xml <?xml version=" ...

  2. 阿里云研究员叔同:Serverless 正当时!

    作者 | 叔同 导读:Serverless 将开发人员从繁重的手动资源管理和性能优化中解放出来,就像数十年前汇编语言演变到高级语言的过程一样,云计算生产力再一次发生变革.Serverless 的核心价 ...

  3. Centos7 python3环境搭建 兼容python2.7

    Centos7 python3环境搭建 兼容python2.7 安装前提依赖 yum install openssl-devel bzip2-devel expat-devel gdbm-devel ...

  4. Python 做简单的登录系统

    案例 之 登录系统原创作品1 该随笔 仅插入部分代码:全部py文件源代码请从百度网盘自行下载! 链接:https://pan.baidu.com/s/1_sTcDvs5XEGDcnpoQEIrMg 提 ...

  5. DOM的本质 和 方法

    <JavaScript DOM编程艺术> 读书笔记 一句话解释DOM: DOM,即我们所看到的网页,其在浏览器背后的文档结构(树状分支结构),涵盖了每一个节点(称之为对象).可以通过JS等 ...

  6. 类图示例-订单系统 / Class Diagram - Order System

    类图示例-订单系统 / Class Diagram - Order System 什么是类图? 类图通过显示它的类和它们之间的关系来概述系统.类图是静态的 - 它们显示交互的内容,但不显示交互时会发生 ...

  7. [no code][scrum meeting] Beta 12

    $( "#cnblogs_post_body" ).catalog() 例会时间:5月27日11:30,主持者:乔玺华 一.工作汇报 人员 昨日完成任务 明日要完成的任务 乔玺华 ...

  8. 【二食堂】Alpha - Scrum Meeting 7

    Scrum Meeting 7 例会时间:4.17 11:40 - 12:00 进度情况 组员 昨日进度 今日任务 李健 1. 继续文本区域的开发,先完成目前简陋的添加方式,再区实现勾选功能issue ...

  9. 攻防世界 杂项 12.Training-Stegano-1

    题目描述: 这是我能想到的最基础的图片隐写术.啊这 题目分析: 最初还以为直接右击属性查看呢 然后用notepad++看看,一团乱码,结果在最后发现了passwd, 然后这就是flag:stegano ...

  10. 源码解析-Abp vNext丨分布式事件总线DistributedEventBus

    前言 上一节咱们讲了LocalEventBus,本节来讲本地事件总线(DistributedEventBus),采用的RabbitMQ进行实现. Volo.Abp.EventBus.RabbitMQ模 ...