zoukankan      html  css  js  c++  java
  • 高精度 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<<"
    ";
            cout<<x;
        }
        return 0;
    }
  • 相关阅读:

    c#常用的基础概念
    Visual Studio2010+SOS.dll调试入门 摘自 http://www.cnblogs.com/luminji/archive/2011/01/27/1946217.html
    优化数据库之前的10个问题
    js数组清空的两种方式
    我的资源(网站, 工具)
    iis使用十大原则
    SQL2005分页存储过程
    温故而知新:Delegate,Action,Func,匿名方法,匿名委托,事件
    无法获得数据库 'model' 上的排他锁 网上搜索结果 IT
  • 原文地址:https://www.cnblogs.com/qingjiuling/p/11398778.html
Copyright © 2011-2022 走看看