高精度 CF567(Div2) Split a Number

题目链接:https://www.luogu.org/problem/CF1181B

题意:给你一个l(2<=l<=100000)位正整数n,将其划分成没有前导0的非空的两段,使这两段表示的正整数之和最小。数据保证至少有一个合法的划分。

分析:我们知道,模拟高精度加法的时间复杂度是O(N),暴力枚举切割位置那就是O(N^2)的,肯定T,很容易想到从中间开始切割.

我们直接分别从中间开始向左边和向右边划分,两边能找到的第一个情况就是最小情况(因为此时两部分位数相差最小)

思想很简单,高精度加法仔细看看,像为什么要颠倒,进位如何做到的都给看看。

为了方便理解,画个图

图示便是从左边开始找时w,t的初始位置(注意下标方向)

 

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+7;
const long long mod=998244353;
const int inf=1<<30;
typedef long long ll;
#define meminf(a) memset(a,0x3f,sizeof(a))
#define mem0(a) memset(a,0,sizeof(a));
string a,t,w,x,y;
//x,y分别是左半边得到的最小和以及从右半边得到的最小和 
int main(){
    int l;scanf("%d",&l);
    cin>>a;
    int len=a.length();
    reverse(a.begin(),a.end());
    //这里颠倒是因为高精度加法需要从后往前加的 
    for(int i=len/2;i>=0;i--){
        x="";
        t=a.substr(0,i);
        w=a.substr(i,len-i);
        //此时w其实是圆字符串的左半边再颠倒 
        //w的长度是一定大于等于t的长度的 
        if(w[w.length()-1]=='0'||t[t.length()-1]=='0'||w.empty()||t.empty()) continue;
        //去除前导0和空串的情况
        x=w; 
        //高精度加法 
        for(int i=0;i<t.length();i++){
            x[i]+=t[i]-'0';
        }
        for(int i=0;i<w.length()-1;i++){
            while(x[i]>'9') x[i]-=10,x[i+1]++;
        }
        if(x[x.length()-1]>'9') x[x.length()-1]-=10,x+='1';
        break;//能找到的第一个情况就是从左边得到的最小和 
    }
    for(int i=(len+1)/2;i<len;i++){
        y="";
        w=a.substr(0,i);
        t=a.substr(i,len-i);
        //w的长度是一定大于等于t的长度的,注意和上一个相比,w,t互换位置了 
        if(w[w.length()-1]=='0'||t[t.length()-1]=='0'||w.empty()||t.empty()) continue;
        //去除前导0和空串的情况
        y=w; 
        for(int i=0;i<t.length();i++){
            y[i]+=t[i]-'0';
        }
        for(int i=0;i<w.length()-1;i++){
            if(y[i]>'9') y[i]-=10,y[i+1]++;
        }
        if(y[y.length()-1]>'9') y[y.length()-1]-=10,y+='1';
        break;//能找到的第一个情况就是从右边得到的最小和 
    }
    reverse(x.begin(),x.end());
    reverse(y.begin(),y.end());
    //x,y此时都是个位在最前,变回个位在最后
    if(x.empty())cout<<y<<endl;
    else if(y.empty())cout<<x<<endl;
    else if(x.size()!=y.size()){cout<<(x.size()<y.size()?x:y);return 0;}
    else{
        for(int i=0;i<x.size();i++){
            if(x[i]!=y[i]){
                cout<<(x[i]<y[i]?x:y);
                return 0;
            }

        }//cout<<x<<" "<<y<<"\n";
        cout<<x;
    }
    return 0;
}

 

posted @ 2019-08-23 11:03  清酒令  阅读(305)  评论(0编辑  收藏  举报