原题地址:
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