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 ...
随机推荐
- Windows系统在Python2.7环境下安装numpy, matplotlib, scipy - Lichanghao Blog
numpy, matplotlib, scipy三个包是科学计算和绘图的利器.安装它们既可以在网上下载exe安装包,也可以用python内置的包管理工具来下载安装,后者较为方便. 这几天做美赛要用到, ...
- USB小白学习之路(5) HID鼠标程序
HID鼠标程序 1. 特别注意 需要特别注意,各个例程中的设备描述符,配置描述符等各种描述符都是已经配置好了的,我们需要做的只是在例程中将代码修改为自己需要的部分即可,一般情况下是不可以串搭配的. 2 ...
- 带你学习Javascript中的函数进阶(一)
1. 函数的定义和调用 1.1 函数的定义方式 函数声明方式function关键字(命名函数) 函数表达式(匿名函数) new Function() var fn = new Function('参数 ...
- 名企6年Java程序员的工作感悟,送给迷茫的你
程序员从开始选择到坚持下去,工作了六年对一个程序员意味什么?在职位上:高级开发工程师?架构师?技术经理?or ... ?在能力上:各种编码无压力?核心代码无压力?平台架构无压力? or ... fuc ...
- 如何优化自己的JS代码
尽管接触大大小小项目N多个,但是刚入行两年, 撸码还是没有完全成一定的规律:最近受到很多启发,打算沉淀沉淀自己的代码: 之前很多页面的很多js脚本本分代码,更注重效果,事件久后没有发展 性能也是很关键 ...
- Taro_Mall 是一款多端开源在线商城小程序.
介绍 Taro_Mall是一款多端开源在线商城应用程序,后台是基于litemall基础上进行开发,前端采用Taro框架编写,现已全部完成小程序和h5移动端,后续会对APP,淘宝,头条,百度小程序进行适 ...
- 「前端」rem 缩放方案 flexible-js 兼容 375px 方案的思路
本文来自尚妆前端团队南洋 发表于尚妆github博客,欢迎订阅. 移动端H5页面rem缩放方案flexible.js兼容375px方案的思路 参考: 移动端高清.多屏适配方案 viewport-and ...
- 利用 Rize 来进行 UI 测试或 E2E 测试
之前我曾经在<Rize - 一个可以让你简单.优雅地使用 puppeteer 的 Node.js 库>一文简单介绍过 Rize 这个库.当时仅仅是介绍这个库本身,关于如何使用,我没有给太多 ...
- Nginx server name配置子域名二级域名
绑定子域名到不同目录(子站) 网站的目录结构为 /var/www/html: ├── fx └── blog└── photo html为nginx的默认网站目录. sudo vi /etc/ngin ...
- ggplot2(4) 用图层构建图像
4.1 简介 qplot()的局限性在于它只能使用一个数据集和一组图形属性映射,解决这个问题的办法就是使用图层.每个图层可以有自己的数据集和图形属性映射,附加的数据元素可通过图层添加到图形中. 一个图 ...