CodeForces - 697B Barnicle (高精度小数点)

6 篇文章 0 订阅

原题地址:
CodeForces-697B

题意描述:
输入一个科学计数法表示的数字,形式如: a.deb (0 ≤ a ≤ 9, 0 ≤ d < 10^100, 0 ≤ b ≤ 100,d无多余的后导0) 以普通书写的方式输出该数字

题目吐槽:
这个题看着简单,但是我的算法改善就改善了四个版本。小数点的控制好麻烦,尤其有有时候要0,有时候又不要0,前导0,后导0,小数点前补个0。麻烦死了。
但是吧,嘻嘻,找到简洁好理解的办法了。
提醒一下:a , d , b是可以等于0的,但是格式不变。。。MDZZ,可能我上了假学校学了假数学,写的都是假科学计数法。

解决方案:
借鉴高精度的处理方式,将每一位数字都单独记录在数组中,调整小数点顺序后输出。
首先把小数点 “.”之前的数字每一位都放在数组中,然后再将小数点之后 “e”之前的数字放在双端容器中,这样每一个数字就是独立的了。最后将“e”后的数字转化为整形b。

之后,循环 b 次,每次都将双端容器的首位放在数组的最后面,然后从双端容器中把最前面的数字删除,以此模拟原数乘十的操作。注意,如果双端容器已空则在数组之后补0.
最后一次输出数组中的数字,再输出 “.”,在从前向后输出双端容器中的数字(注意,如果双端容器是空的,“.”不要输出)

再有一个比较诡异的情况就是 “0.0e0”“1.0e0”“2.0e0”。。。
由于小数点之后的0是多读入的,但是有没有实际意义,当e等于0时就会造成双端容器中出现不该出现的数字0,导致输出 “0.0””1.0” 等错误答案,应在一开始就排除这种情况。

另一种暴力的模拟算法是自己一开始脑子不运转写的,补了好多漏洞才改好,贴在最下面供参考。
还有一种通过把字符退回流里的骚做法在最最下面(Double不够长,WA了)。

下面贴出题解AC代码:

#include<iostream>
#include<string>
#include<vector>
#include<deque>
using namespace std;
int main(){
    vector<int> AA;
    deque<int> BB;
    string num;
    cin>>num;
    int dot=-1,pos=-1,e=0;
    for(int i=0;i!=num.size();i++){
        if(num[i]=='.'){
            dot=i;
            continue;
        }
        if(num[i]=='e'){
            pos=i;
            continue;
        }
        if(dot==-1){
            AA.push_back(num[i]-'0');
        }else if(pos==-1){
            BB.push_back(num[i]-'0');
        }else{
            e*=10;
            e+=num[i]-'0';
        }
    }
    while(e--){
        if(BB.empty()){
            AA.push_back(0);
        }else{
            AA.push_back(BB.front());
            BB.pop_front();
        }
    }
    for(int i=0;i!=AA.size();i++){
        cout<<AA[i];
    }
    if((BB.size()==1&&BB[0]==0)||BB.size()==0){
        return 0;
    }
    cout<<'.';
    for(int i=0;i!=BB.size();i++){
        cout<<BB[i];
    }
    return 0;
}
//Designed by wolf

早期AC代码:

#include<iostream>
#include <iomanip>
#include<string>
#include<cmath>
using namespace std;
int main(){
    string num;
    cin>>num;
    bool zero=0;
    int pos,e,ne=0;
    pos=num.find('.');
    e=num.find('e');
    for(int i=e+1;i!=num.size();i++){
        ne*=10;
        ne+=num[i]-'0';
    }
    if(ne==0){
        if(e==3&&num[2]=='0'){
            cout<<num[0]-'0';
            return 0;
        }
        cout<<num.substr(0,e);
        return 0;
    }else if(num[0]=='0'){
        bool flag=0,zero=0,hh=1;
        for(int i=pos+1;i<e;i++){
            if(num[i]!='0'){
                flag=1;
                zero=1;
            }
            if(flag||ne<=0){
                if(ne==0){
                    if(hh){
                        cout<<0;
                    }
                    cout<<'.';
                }
                cout<<num[i];
                hh=0;
            }
            ne--;
        }
        if(zero){
            for(int i=0;i<ne;i++){
                cout<<0;
            }
        }else{
            cout<<0;
        }
        return 0;
    }else{
        cout<<num[0];
        for(int i=pos+1;i<e;i++){
            if(ne==0){
                cout<<'.';
            }
            cout<<num[i];
            ne--;
        }
        for(int i=0;i<ne;i++){
            cout<<0;
        }
        return 0;
    }
    return 0;
}
//Designed by wolf

再贴一个超级骚的,但是由于Double只有15位小数点所以WA了的代码:

#include<iostream>
#include<sstream>
#include <iomanip>
#include<string>
#include<cmath>
using namespace std;
int main(){
    string num;
    cin>>num;
    int pos;
    pos=num.find('e');
    if(num[num.size()-1]=='0'){
        if(pos==3&&num[2]=='0'){
            cout<<num[0]-'0';
            return 0;
        }
    }
    stringstream ss,dd;
    ss<<num.substr(pos+1);
    dd<<num.substr(0,pos);
    int e;
    double n;
    ss>>e;
    dd>>n;
    for(int i=0;i!=e;i++){
        n*=10;
    }
    int pre;
    pre=pos-2-e;
    if(pre<0){
        pre=0;
    }
    cout<<std::fixed<<setprecision(pre)<<n<<endl;
    return 0;
}
//Designed by wolf
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值