Codeforces Round #567 (Div. 2) B. Split a Number
2 seconds
512 megabytes
standard input
standard output
Dima worked all day and wrote down on a long paper strip his favorite number nn consisting of ll digits. Unfortunately, the strip turned out to be so long that it didn't fit in the Dima's bookshelf.
To solve the issue, Dima decided to split the strip into two non-empty parts so that each of them contains a positive integer without leading zeros. After that he will compute the sum of the two integers and write it down on a new strip.
Dima wants the resulting integer to be as small as possible, because it increases the chances that the sum will fit it in the bookshelf. Help Dima decide what is the minimum sum he can obtain.
The first line contains a single integer ll (2≤l≤1000002≤l≤100000) — the length of the Dima's favorite number.
The second line contains the positive integer nn initially written on the strip: the Dima's favorite number.
The integer nn consists of exactly ll digits and it does not contain leading zeros. Dima guarantees, that there is at least one valid way to split the strip.
Print a single integer — the smallest number Dima can obtain.
7
1234567
1801
3
101
11
In the first example Dima can split the number 12345671234567 into integers 12341234 and 567567. Their sum is 18011801.
In the second example Dima can split the number 101101 into integers 1010 and 11. Their sum is 1111. Note that it is impossible to split the strip into "1" and "01" since the numbers can't start with zeros.
题意:有一个数n,长度为l,l是n的位数有多少个,注意l最多有1e5(这是什么一个概念,long long 最多有18位,一开始我理解错题意了,就用long long写了)
要求将这个数n分割为2个没有前导0的正整数使得这2个正整数和最小
思路:注意到l最大有1e5,爆long long了,就祭出大数加法模板,现在就考虑怎么分的问题
怎样分才能让两个数之和最大?贪心地想是从中间开始分,但要考虑中间为0和长度为基数的情况,所以就要考虑是左边的数更长一点好还是右边的数更长一点好
先优先把mid选在右边,因为一个数的开头不能有前导0(单个0不算前导0),如果mid那一位为0,向右扩展mid,如果中间没有前导0且长度为基数,则会产生左右数长度不等的情况,所以要看mid这个数给左边能使他们两个之和更小还是给右边能使他们两个之和更小
现在默认mid放右边的数,从最高位依次判断两个数的大小如果左边的比右边的更小则把中间这个数给左边,使左边增加一位,右边减少一位,这样两个数之和是更小的,因为,左边那一位小于右边那一位了,左边增加的肯定是小于右边减少的,故能使整体之和更小,举个例子,123中间是2,现在默认给右边的,分开来就是1,23,现在来判断,1<2,则把中间那个给左边的数,变成12,3,现在发现,左边增加了11,右边减少了20,所以左边增加的小于右边减少的,那么总体是减少的
注意mid右边不能为0才能右移因为,不然就有前导0了,而如果左边的数大于右边的数,那么把中间这个数放右边是更优的
接下来优先把mid放左边,与上面同理,注意因为2次mid可能算的不一样,所以n1,n2记得要清0,不然可能会保留上一次的东西,一开始因为没清零WA了几次
最后判断是mid放左边更小还是mid放右边更小,选一个小的输出
#include<bits/stdc++.h>
using namespace std;
const int amn=1e5+;
char in[amn],n1[amn],n2[amn];
int l,tp;
struct bignum{ ///大数加法的模板
int len,n[amn];
void getnum(char in[]){
len=strlen(in);
for(int i=;i<len;i++){
n[i]=in[len-i-]-'';
}
}
void add(bignum a,bignum b){
int le=max(a.len,b.len);
int x,c=;
len=;
for(int i=;i<le||c;i++){
x=c;
if(i<a.len)x+=a.n[i];
if(i<b.len)x+=b.n[i];
c=x/;
x%=;
n[i]=x;
len++;
}
}
int big(bignum a,bignum b){ ///比较大小
if(a.len>b.len)return ;
if(a.len<b.len)return -;
for(int i=a.len-;i>=;i--){
if(a.n[i]>b.n[i])return ;
if(a.n[i]<b.n[i])return -;
}
return ;
}
void out(){
for(int i=len-;i>=;i--){
printf("%c",n[i]+'');
}
printf("\n");
}
}a,b,c,d;
int fd(int x,int d){
int lx=x;
if(d) ///看现在要向左扩展还是向右扩展
while(in[x]==''&&x>=)x--; ///因为一个数的开头不能有前导0(单个0不算前导0)如果mid那一位为0,向左扩展mid
else
while(in[x]==''&&x<l)x++; ///如果mid那一位为0,向右扩展mid
if((x==l/)&&l%){ ///如果中间没有前导0且长度为基数,则会产生左右数长度不等的情况,所以要看mid这个数给左边能使他们两个之和更小还是给右边能使他们两个之和更小
for(int i=;i<=x;i++){ ///现在默认mid放右边的数
if(in[i]<in[i+x]){ ///从最高位依次判断两个数的大小如果左边的比右边的更小则把中间这个数给左边,使左边增加一位,右边减少一位,这样两个数之和是更小的,因为,左边那一位小于右边那一位了,左边增加的肯定是小于右边减少的,故能使整体之和更小,举个例子,123中间是2,现在默认给右边的,分开来就是1,23,现在来判断,1<2,则把中间那个给左边的数,变成12,3,现在发现,左边增加了11,右边减少了20,所以左边增加的小于右边减少的,那么总体是减少的
if(in[x+1]!='0')///mid右边不能为0才能右移因为,不然就有前导0了
x++;
break;
}
else if(in[i]>in[i+x]) break; ///如果左边的数大于右边的数,那么把中间这个数放右边是更优的
}
}
return x;
}
int main(){
ios::sync_with_stdio();
cin>>l>>in; ///怎样分才能让两个数之和最大?贪心地想是从中间开始分,但要考虑中间为0和长度为基数的情况,所以就要考虑是左边的数更长一点好还是右边的数更长一点好
int mid=fd(l/,); ///优先把mid选在右边
for(int i=;i<mid;i++)
n1[i]=in[i];
tp=;
for(int i=mid;i<l;i++)
n2[tp++]=in[i];
a.getnum(n1),b.getnum(n2);
c.add(a,b); ///大数加法,下面同理
mid=fd(l/,); ///优先把mid选在左边
memset(n1,,sizeof n1); ///因为2次mid可能算的不一样,所以n1,n2记得要清0,不然可能会保留上一次的东西
memset(n2,,sizeof n2);
for(int i=;i<mid;i++)
n1[i]=in[i];
tp=;
for(int i=mid;i<l;i++)
n2[tp++]=in[i];
a.getnum(n1),b.getnum(n2);
d.add(a,b);
if(a.big(c,d)<) ///选一个小的输出
c.out();
else
d.out();
}
/***
有一个数n,长度为l,l是n的位数有多少个,注意l最多有1e5(这是什么一个概念,long long 最多有18位,一开始我理解错题意了,就用long long写了)
要求将这个数n分割为2个没有前导0的正整数使得这2个正整数和最小
注意到l最大有1e5,爆long long了,就祭出大数加法模板,现在就考虑怎么分的问题
怎样分才能让两个数之和最大?贪心地想是从中间开始分,但要考虑中间为0和长度为基数的情况,所以就要考虑是左边的数更长一点好还是右边的数更长一点好
先优先把mid选在右边,因为一个数的开头不能有前导0(单个0不算前导0),如果mid那一位为0,向右扩展mid,如果中间没有前导0且长度为基数,则会产生左右数长度不等的情况,所以要看mid这个数给左边能使他们两个之和更小还是给右边能使他们两个之和更小
现在默认mid放右边的数,从最高位依次判断两个数的大小如果左边的比右边的更小则把中间这个数给左边,使左边增加一位,右边减少一位,这样两个数之和是更小的,因为,左边那一位小于右边那一位了,左边增加的肯定是小于右边减少的,故能使整体之和更小,举个例子,123中间是2,现在默认给右边的,分开来就是1,23,现在来判断,1<2,则把中间那个给左边的数,变成12,3,现在发现,左边增加了11,右边减少了20,所以左边增加的小于右边减少的,那么总体是减少的
注意mid右边不能为0才能右移因为,不然就有前导0了,而如果左边的数大于右边的数,那么把中间这个数放右边是更优的
接下来优先把mid放左边,与上面同理,注意因为2次mid可能算的不一样,所以n1,n2记得要清0,不然可能会保留上一次的东西,一开始因为没清零WA了几次
最后判断是mid放左边更小还是mid放右边更小,选一个小的输出
***/
Codeforces Round #567 (Div. 2) B. Split a Number的更多相关文章
- Codeforces Round #567 (Div. 2)B. Split a Number (字符串,贪心)
B. Split a Number time limit per test2 seconds memory limit per test512 megabytes inputstandard inpu ...
- DP+埃氏筛法 Codeforces Round #304 (Div. 2) D. Soldier and Number Game
题目传送门 /* 题意:b+1,b+2,...,a 所有数的素数个数和 DP+埃氏筛法:dp[i] 记录i的素数个数和,若i是素数,则为1:否则它可以从一个数乘以素数递推过来 最后改为i之前所有素数个 ...
- 数学+DP Codeforces Round #304 (Div. 2) D. Soldier and Number Game
题目传送门 /* 题意:这题就是求b+1到a的因子个数和. 数学+DP:a[i]保存i的最小因子,dp[i] = dp[i/a[i]] +1;再来一个前缀和 */ /***************** ...
- Codeforces Round #567 (Div. 2)自闭记
嘿嘿嘿,第一篇文章,感觉代码可以缩起来简直不要太爽 打个div2发挥都这么差... 平均一题fail一次,还调不出错,自闭了 又一次跳A开B,又一次B傻逼错误调不出来 罚时上天,E还傻逼了..本来这场 ...
- Codeforces Round #567 (Div. 2)A
A. Chunga-Changa 题目链接:http://codeforces.com/contest/1181/problem/A 题目 Soon after the Chunga-Changa i ...
- Codeforces Round #514 (Div. 2) E. Split the Tree(倍增+贪心)
https://codeforces.com/contest/1059/problem/E 题意 给出一棵树,每个点都有一个权值,要求你找出最少条链,保证每个点都属于一条链,而且每条链不超过L个点 和 ...
- Codeforces Round #567 (Div. 2) E2 A Story of One Country (Hard)
https://codeforces.com/contest/1181/problem/E2 想到了划分的方法跟题解一样,但是没理清楚复杂度,很难受. 看了题解觉得很有道理,还是自己太菜了. 然后直接 ...
- Codeforces Round #567 Div. 2
A:签到. #include<bits/stdc++.h> using namespace std; #define ll long long #define inf 1000000010 ...
- Codeforces Round #567 (Div. 2) A.Chunga-Changa
原文链接:传送 #include"algorithm" #include"iostream" #include"cmath" using n ...
随机推荐
- 空间数据导入Oracle数据库备忘
- Leetcode 943. Find the Shortest Superstring(DP)
题目来源:https://leetcode.com/problems/find-the-shortest-superstring/description/ 标记难度:Hard 提交次数:3/4 代码效 ...
- Spring-cloud微服务实战【十】:消息总线Bus
回忆一下,在上一篇文章中,我们使用了分布式配置中心config来管理所有微服务的配置文件,那这样有没有什么问题?有,那就是无法配置文件无法自动更新,当我的git服务器上的配置文件更新后,不能同步更 ...
- python类变量与构造函数的使用
类变量:可在类的所有实例之间共享的变量 实例类对象:类的实例是调用类对象来创建的.如:par = Parent(),par就是类Parent的一个实例类对象. 实例变量(成员变量):同一个类对象可以创 ...
- Nginx之反向代理配置(二)
前文我们聊了Nginx的防盗链.反向代理以及开启nginx代理缓存,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/12417130.html:今天我们继续说ng ...
- 天坑,CSS之定位Position(六分之五)
Position定位 个人觉得position这个属性真的算是CSS的见面杀了.尤其是absolute,当年可是被虐的不轻.当然了,现在爱上了这个属性,谁用谁知道. position属性 positi ...
- python笔记26
一.今日内容 python中的方法 python中的方法+正则表达式的新内容 #分组 #分组命名 #引用分组 #爬虫的小例子 1.转义符 如:\n--->\\n--->print('\\n ...
- Tomcat 之startup.bat启动失败案例
今天我在部署一个Tomcat环境时,各种变量都配置完了,最后启动Tomcat时,Tomcat一闪而过,当时我的内心是崩溃的~~ 然后我就开始百度.定位问题.进入cmd命令行窗口,cd进入到Tomcat ...
- 数据库--Redis
原因: 源码是官方configure过的,但官方configure时,生成的文件有时间戳信息,所以如果你的虚拟机的时间不对,比如说是2022年,就可能会出错 解决: date -s ‘yyyy-mm- ...
- npm install、npm install --save与npm install --save-dev、npm install -g区别
npm install X: 会把X包安装到node_modules目录中 不会修改package.json 之后运行npm install命令时,不会自动安装X npm install X –sav ...