洛谷 U140098 计数
题目背景
从古到今,人类的计数方式有着显著的进步。
追溯到五千年到八千年前,这时,四大文明古国都早已从母系社会过渡到父系社会了,生产力的发展导致国家雏形的产生,生产规模的扩大则刺激了人们对大数的需要。比如某个原始国家组织了一支部队,国王陛下总不能老是说:“我的这支战无不胜的部队共计有9名士兵!”于是,慢慢地就出现了“十”、“百”、“千”、“万”这些符号。在我国商代的甲骨文上就有“八日辛亥允戈伐二千六百五十六人”的刻文:即在八日辛亥那天消灭敌人共计2656人。在商周的青铜器上也刻有一些大的数字,以后又出现了“亿”、“兆”这样的大数单位。
而在古罗马,最大的记数单位只有“千”.他们用M表示一千.“三千”则写成“MMM”.“一万”就得写成“MMMMMMMMMM”。难以想象,如果他们需要记一千万时怎么办,难道要写上一万个M不成?
总之,人们为了寻找记大数的单位是花了不少脑筋的。旧社会在农村读私塾,一些私塾先生会教:“最大的数叫‘猴子翻跟斗’”。这位私塾先生可能认为孙悟空一个跟斗翻过去的路程是最最远的,不能再远了,所以完全可以用“猴子翻跟斗”来表示最大的数。在古印度,使用了一系列大数单位后,最后的最大的数的单位叫做“恒河沙”.是呀,恒河中的沙子谁数得清!
然而,古希腊有一位伟大的学者,他却数清了“充满宇宙的沙子数”,那就是阿基米德.他写了一篇论文,叫做《计沙法》。在这篇文章中,他提出的记数方法,同现代数学中表示大数的方法很类似。他从古希腊的最大数字单位“万”开始,引进新数“万万(亿)”作为第二阶单位,然后是“亿亿”(第三阶单位),“亿亿亿”(第四阶单位),等等,每阶单位都是它前一阶单位的1亿倍。阿基米德的同时代人、天文学家阿里斯塔克斯曾求出地球到天球面距离10,000,000,00010,000,000,000斯塔迪姆(11斯塔迪姆=188=188米)。这个距离当然比现在我们所认识的宇宙要小得多,这才仅仅是太阳到土星的距离。阿基米德假定这个“宇宙”里充满了沙子.然后开始计算这些沙子的数目。最后他写道:“显然,在阿里斯塔克斯计算出的天球里所能装入的沙子的粒数,不会超过一千万个第八阶单位”。如果要把这个沙子的数目写出来,就是10,000,000×(100,000,000)_710,000,000×(100,000,000)7或者就得在11后边写上6363个00:1,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,0001,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000。这个数,我们现在可以把它写得简单一些:即写成1×10^{63}1×1063。而这种简单的写法,据说是印度某个不知名的数学家发明的。这种用在11与1010间的一个数乘以1010的若干次幂的记数方法就是“科学记数法”。
用科学记数法表示数时,不改变数的符号,只是改变数的书写形式而已,可以方便的表示日常生活中遇到的一些极大或极小的数。
如:光的速度大约是300,000,000300,000,000米/秒;全世界人口数大约是:6,100,000,0006,100,000,000.
这样的数,读、写都很不方便,我们可以免去写这么多重复的00,将其表现为这样的形式:
6,100,000,000=6.1×10^96,100,000,000=6.1×109
或:
0.00001=1×10^{-5}0.00001=1×10−5
即绝对值小于1的数也可以用科学记数法表示为aa乘1010的负nn次方的形式。
题目描述
虽然科学记数法是小学四年级的数学知识。但是为了纪念出题人在CSP-S2020CSP−S2020的考场上被坐在身旁的小学生反复敲打,现将科学记数法的记法向选手叙述。对于不同选手可能存在的对科学计数法的认知差别,皆以本叙述为准:
对于一个数xx:
1、若|x|>1∣x∣>1,则记为a imes 10n*a*×10*n*的形式。n*n*的值由x*x*的位数决定,设m*m*为x*x*的位数,则n=m-1*n*=*m*−1,a=frac{x}{10n}a=10n**x。
2、若|x|<1∣x∣<1,则n=-(m-m_1),a=x imes 10^{m-m_1}n=−(m−m1),a=x×10m−m1,其中mm为xx的位数,m_1m1为xx的有效数位。
与此同时,在计算数学中,数学家们引入了新的符号EE以代替这种1010的整数次幂的表示形式。具体地,有:
1、a imes 10^n=aEna×10n=aEn。
2、特别地,当n=0n=0时,省略E0E0。
根据以上规律,编写程序,解决“给出一个合法的十进制数,求其科学记数法表示”这类问题是很容易的。我们当下面临的问题是:不保证给出的十进制数合法。具体地,有:
1、可能出现若干前置0。
2、可能出现若干后置0。
3、小数点可以单独出现而不需要前后缀。即:.612.612和914.914.这类数都是有可能出现的。
那么,现在给你一个长度为NN的、符合以上要求的数字,请你按以上要求编写程序,求出其正确的科学计数法表示。
输入格式
从文件count.incount.i**n中读入数据。
一行一个长度为NN的字符串,描述一个待转换的数字。
输出格式
输出到文件count.outcount.out中。
一行一个字符串,表示这个数字的合法科学计数法表示。
命题背景:
为了纪念CSP-S2020 T1挂分,特意出了这道题来训练选手的审题及对各种复杂数据的调试能力。
也就是从废话连篇的题面中提取关键信息。但是说实在的,这套题出的还是有些不好,因为前面的真的就是纯废话,中间一点有价值的东西都没有,所以不看也罢。
但是拿这玩意搞搞选手心态练练选手心理素质,并且练练码力,我觉得也是不错的啊。
所以还是有很大价值的。
题解:
解法不唯一,依照题意模拟即可。
加入了很多hack数据来细节。
可能标算都不太细节。但是标算切了。
所以数据以我的为准吧。
代码:
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=1e6+6;
char ori[maxn];
bool flag;
int main()
{
scanf("%s",ori+1);
int len=strlen(ori+1);
int l=1,r=len;
int ppos=0;
if(len==1)
{
printf("%c
",ori[l]);
return 0;
}
while(ori[l]=='0')
l++;
if(ori[r]=='.')
r--;
for(int i=l;i<=r;i++)
if(ori[i]=='.')
{
ppos=i;
flag=1;
break;
}
if(ppos==len)
flag=0;
if(ppos==l)
{
l++;
while(ori[r]=='0')
r--;
if(ori[r]=='.')
r--;
while(ori[l]=='0')
l++;
int cnt=0;
while(cnt<=r-l)
{
if(cnt==1)
printf(".");
printf("%c",ori[l+cnt]);
cnt++;
}
printf("E%d
",-(l-ppos));
return 0;
}
else if(flag==1)
{
while(ori[r]=='0')
r--;
if(ori[r]=='.')
r--;
while(ori[r]=='0')
r--;
int cnt=0;
while(cnt<=r-l)
{
if(cnt==1)
printf(".");
if(ori[l+cnt]=='.')
{
cnt++;
continue;
}
printf("%c",ori[l+cnt]);
cnt++;
}
if(ppos-l-1==0)
return 0;
printf("E%d
",ppos-l-1);
return 0;
}
else if(flag==0)
{
if(l==r)
{
printf("%c",ori[l]);
return 0;
}
int cnt=0;
int zhi=r-l;
while(ori[r]=='0')
r--;
while(cnt<=r-l)
{
if(cnt==1)
printf(".");
printf("%c",ori[l+cnt]);
cnt++;
}
printf("E%d
",zhi);
return 0;
}
return 0;
}