题目粗心:

给定两个位数不超过100的非负浮点数,如果保留n位有效数字的状况下写成0.@@@@*10^@的模式,如果两者雷同,则输入YES和该数字,如果不同输入NO并且别离输入2个数。

算法思路:

认真思考下,这种模式和科学技术法很类似然而有不同于迷信计数法,因为后面肯定得是0.结尾,那么输出的数字的模式依照情理来说只有一种
那就是$abcd.efg$,然而在这里认真分成2类,一类就是$0.efg$ 的模式,一类就是$abcd.@@@$ 的模式(如同和没说一样,哈哈哈),这里把第一类分进去是因为在解决第二类的时候会呈现$abcd$全副是0的状况(这是一个陷阱),这样就进化到了第一类,而后就是输出的数字有可能原本就是第一类,这样不便代码解耦(个人观点),接下来就具体说这2类数字的解决办法.

第一类$0.efg$

首选咱们晓得最初肯定是0.结尾,所以应用string r="0."保留最初后果,这类数字分为2种状况,一种就是小数点前面全是0,这种状况下就
间接让r前面增加n个0和10^0即可(这也是一个陷阱),另外一种就是小数点前面有不为0的数字,那么用index保留其地位,让r增加原字符串的index到最初地位的子串,留神如果该子串的长度s.size()-index<n,则得在前面补充0,使得其小数点前面的无效位为n(这也是一个陷阱),而后再增加指数局部,指数的次幂pos+1-index(index-pos-1就是小数点到不为0之间0的个数,相反数就是指数局部) 。最初返回r即可。该类数字应用type1函数解决。

第二类$abcd.@@@$(蕴含整数)

这类数字也分为2种状况,第一种状况就是小数点后面全副是0,这样的数字(比方0000.@@@,等效于0.@@@)等价于第一类数字,间接将小数点前
面的一个0到最初地位截断,而后调用type1解决即可,第二种状况就是小数点后面有不为0的数字,这样咱们用index保留小数点后面不为0的数字的地位,同样的让r初始化为"0."而后再移除小数点(移到后面去了),将index前面n位子字符串拼接到r的前面,如果该子字符串的长度s.size()-index<n,要在前面补0,最初再增加指数局部,指数的次幂为pos-index(pos-index为小数点后面不为0数字的个数,也就是小数点挪动的位数)

留神点:

1、数字签名可能会有前导0,比方000 000.12 00004522145.155,测试点2,4,6考查,解决办法能够采取去除前导0,这里是间接归类于第二类,而后会跳转到第一类,间接解决小数点前面的数字即可。
2、对于000.00的状况须要输入0.@@@(n个@)*10^0,测试点6考查。
3、对于整数的解决,这里采纳在最初增加一个小数点演绎在第二类中。
4、对于自身不须要挪动小数点的状况,除了000.00这样的须要在最初增加10^0外,其余的点没有考查,也就是像0.12保留2位数字输入0.12和0.12*10^0都是能够的。

提交后果:

测试数据:

4 0000 0000.00 //YES 0.0000*10^0
4 00123.5678 0001235 //NO 0.123510^3 0.123510^4
3 0.0520 0.0521 // NO 0.52010^-1 0.52110^-1
4 00000.000000123 0.0000001230 // YES 0.1230*10^-6
4 00100.00000012 100.00000013 // YES 0.1000*10^3
5 0010.013 10.012 // NO 0.1001310^2 0.1001210^2
4 123.5678 123.5 // YES 0.1235*10^3
3 123.5678 123 // YES 0.123*10^3
4 123.0678 123 // YES 0.1230*10^3
3 0.000 0 // YES 0.000*10^0

AC代码:

#include<cstdio>#include<string>using namespace std;string type1(string s,int n,int pos){//解决模式0.*****的字符串    string r = "0.";//保留最初后果     int index;//保留小数点前面第一个不为0的地位     for(index=pos+1;index<s.size();++index){        if(s[index]!='0') break;    }    if(index==s.size()){//阐明小数点前面全副为0(或者小数点前面没有了,比方输出了0),取无效长度的0,而后增加10^0即可         for(int i=0;i<n;++i){//最初一个测试点考查的就是这一点             r += "0";        }        r += "*10^0";    }else{//存在不为0的数字,那么该数字前面n位为无效位,不够补0         r += s.substr(index,n);        if(s.size()-index<n){//阐明无效位长度不够,得补0             for(int i=0;i<n-(s.size()-index);++i){                r += "0";            }        }        r += "*10^"+to_string(pos+1-index);//index-pos-1就是小数点到不为0之间0的个数,相反数就是指数局部     }    return r;} string type2(string s,int n,int pos){//解决模式abcd.*****     int index;//保留小数点后面第一个不为0的地位    string r;//保留最初后果     for(index=0;index<pos;++index){        if(s[index]!='0') break;    }     if(index==pos){//小数点后面全副是0,从小数点前面找,转化为type1类型         s = s.substr(pos-1);//截取0.*****局部         r = type1(s,n,1);//pos地位就是1     }else{//小数点后面有不为0的局部         r += "0.";        s.erase(s.begin()+pos);//移除小数点         r += s.substr(index,n);//截取index前面n为字符串,不够补0        if(s.size()-index<n){//无效位不够,补0             for(int i=0;i<n-(s.size()-index);++i){                r += "0";            }         }         r += "*10^"+to_string(pos-index);//增加指数局部     }    return r;}string process(string s,int n){//将以后数字写成0.*****的模式并且保留n位     if(s.find(".")==string::npos){//以后字符串没有小数点是整数         s += ".";//在最初增加小数点     }    int pos = s.find(".");//取得小数点的下标     string r;//保留最终后果     if(pos==1&&s[0]=='0'){//该数字原本就是0.****的模式         r = type1(s,n,pos);    } else{//abcd.****的模式        r = type2(s,n,pos);    }    return r; }int main(){    int n;    string s1,s2;    char t1[101],t2[101];    scanf("%d %s %s",&n,t1,t2);    s1 = t1;    s2 = t2;    s1 = process(s1,n);    s2 = process(s2,n);    if(s1==s2){        printf("YES %s",s1.c_str());    }else{        printf("NO %s %s",s1.c_str(),s2.c_str());    }    return 0;}