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

    基本概念 Docker 是什么 Docker 起初是 dotCloud 公司创始人 Solomon Hykes 在法国的时候发起的一项公司内部项目,Docker 是基于 dotCloud 公司多年云服 ...

  2. HPE ProLiant 系列服务器Microsoft Windows 2008 R2系统下网卡绑定方法

    HPE Network Configuration Utility(以下简称NCU) 网卡绑定工具,用户可以通过该工具很方便的把服务器的多个网卡捆绑到一起以达到容错和增加可用带宽的目的. 1.打开NC ...

  3. Apache ShardingSphere 元数据加载剖析

    唐国城 小米软件工程师,主要负责 MIUI 浏览器服务端研发工作.热爱开源,热爱技术,喜欢探索,热衷于研究学习各种开源中间件,很高兴能参与到 ShardingSphere 社区建设中,希望在社区中努力 ...

  4. SQL Server链接服务器信息查询

    exec sp_helpserver --查询链接服务器select * from sys.servers --查询链接服务器链接地址

  5. ArcPy获取栅格属性

    获取栅格属性 (数据管理) 描述 从元数据和栅格数据集的相关描述性统计数据中检索信息. 使用方法 返回的属性将显示在结果窗口中. 此工具的 Python 结果是地理处理结果对象.要获取字符串值,请使用 ...

  6. 洛谷1429 平面最近点对(KDTree)

    qwq(明明可以直接分治过掉的) 但是还是当作联系了 首先,对于这种点的题,很显然的套路,我们要维护一个子树\(mx[i],mn[i]\)分别表示每个维度的最大值和最小值 (这里有一个要注意的东西!就 ...

  7. T-SQL——关于XML类型

    目录 0. 将结果集转化为XML格式 1. 列值拼接为字符串 2. 字符串转换为列值 3. 一些说明 参考 志铭-2021年10月23日 10:43:21 0. 将结果集转化为XML格式 测试数据 I ...

  8. 深入理解Java虚拟机之类加载机制篇

    概述 ​ 虚拟机把描述类的数据从 Class 文件加载到内存中,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,就是虚拟机的类加载机制. ​ 在Java语言里面,类型的 ...

  9. 重学c#系列——list(十二)

    前言 简单介绍一下list. 正文 这里以list为介绍. private static readonly T[] s_emptyArray = new T[0]; public List() { t ...

  10. 【UE4 C++】Actor 与 Component —— 创建、销毁

    Actor的生成与销毁 创建Actor实例 UClass* TSubclassOf<T> SpawnActor() UPROPERTY(EditAnywhere, Category = & ...